0

I'm trying to chain 2 Firebase queries using promises because I need the result of first query to get the second. Here is the structure of the 2 queries:

QUERY FOR VALUE A:

    private getValueA(){
    var queryEvent = (result):void  =>{
        console.dump(result);
        this._valueA = result.value;
    }
    return firebase.query(
        queryEvent,
        FirebaseValueAPath, 
        {
            singleEvent : true,
            orderBy : {
                type: firebase.QueryOrderByType.CHILD,
                value: 'since' 
            }
        });
    }

QUERY FOR VALUE B:

    private getValueB{

        let FirebaseValueBPath :string = this._valueA
        var queryEvent = (result) :void =>{
            console.dump(result);
            if(result.value){
                this._valueB = result.value;
            }
        }
        return firebase.query(
            queryEvent,
            FirebaseValueBPath,
            {
                singleEvent : true,
                orderBy : {
                    type    : firebase.QueryOrderByType.CHILD,
                    value   : 'since'
                }
        });
    }
}

I then try to chain them together by doing the following :

constructor(){
    this.getValueA().then(
     (success) :void => {
    this.getValueB();
   });
}

The result of this is the following :

  1. For some reason console.log(result) inside getValueB function gets printed before console.log(result) inside getValueA function (why??)
  2. this.valueA is undefined in getValueB, making my query useless
  3. App crashes

What is wrong with my code? Should I be using another approach for this problem? Thank you in advance for looking into this :)

Aaron Ullal
  • 4,855
  • 8
  • 35
  • 63

1 Answers1

1

When using promises you have to resolve the result in your callback. Please find the code below :

class GetData {
    constructor() {
        this.getValueA()
            .then(resultA => this.getValueB(resultA));
    }

    getValueA() {
        return new Promise<string>((resolve, reject) => {
            firebase.query(
                (result) => {
                    resolve(result.value); // Resolve => returns the result
                },
                FirebaseValueAPath, 
                {
                    singleEvent : true,
                    orderBy : {
                        type: firebase.QueryOrderByType.CHILD,
                        value: 'since' 
                    }
                }));
        });
    }

    getValueB(valueA: string) {
        return new Promise<string>((resolve, reject) => {
            firebase.query(
                (result) => {
                    resolve(result.value);  // Resolve => returns the result
                },
                valueA, 
                {
                    singleEvent : true,
                    orderBy : {
                        type: firebase.QueryOrderByType.CHILD,
                        value: 'since' 
                    }
                }));
        });
    }
}
Guillaume
  • 844
  • 7
  • 25
  • This did it!! Thanks – Aaron Ullal Sep 27 '16 at 16:48
  • 1
    One question though...isn't this considered an anti pattern? http://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it – Aaron Ullal Sep 27 '16 at 16:53
  • I didn't know the anti-pattern. I've learned something new, thanks ! After analyzing the github page in your link, i don't think that my answer is a, anti-pattern. Because the `firebase.query` does not return a `Promise` with the result. It's a function with result callback. So, if you want to use it in Promise way WITHOUT ANY EXTERNAL LIBRARY, you have to wrap it in `Promise` constructor. Otherwise, you could use the `promisify` library like mentionned in the github page. – Guillaume Sep 28 '16 at 07:34