Search code examples
javascriptpromiseglobal-variables

JavaScript access Promise outside the then function


I am trying to access the value in Promise outside the then function using JavaScript. I am new to Promise and I not sure if I am doing it correctly. Here is my code:

//removed code

Basically I have store the value returned by Promise into a separate variable inside the then function. I wanted to access them at the later part, but when I print them out at later part, it returns me undefined. Any ideas on how to resolve this?

I have found examples and followed them but it does not work. I not sure which part of my code was wrong. I opened a thread earlier on and it was marked as duplicate and closed. I guess my inquiry wasn't clear enough, therefore I am rephrasing the question here.


Solution

  • In order to execute logic when both promises resolved their value you should use the Promise.all() on the promises objects.

      Promise.all([promiseCurrencyKey, promiseStoreKey]).then(values => { 
        console.log(values); 
      });
    

    JavaScript is a single threaded language which means having the code waiting for something to happen will block everything else. Now, we can't really code without things that sometimes might take a while, and this is what Promises are for.

    The logic in a promise is being processed in the background and not blocking the code. In order to use the value resolved by the promise you can set a callback function into the then() method which will be executing when the value is resolved.

    Having the callback executing when the value resolved doesn't make the rest of the code to wait.

    So describing what happen with your code is as follow:

    1. run some logic in the background that resolve value
    2. when value resolved set it to p1
    3. print p1 - the logc in step 1 didn't finish yet, meaning the logic in the then function also didn't happen and value still not set into p1

    Same happen for p2.

    Now, when you are using Promise.all() you are performing it on two simple empty variables and not on the promises objects so the result is array with two empty variables...

    In the second example after the editing the problem is that you defined the promiseBranchKey inside the first promise function so it's exist only for the scope of this function and not out of it where you are calling Promise.all().

    let promiseMerchantKey = new Promise((resolve, reject) => {
        firebase.database().ref('merchants').orderByChild('merchantName').equalTo('NTUC').once('value', function(snapshot) {
            let merchantData = snapshot.val();
            if (merchantData){
                console.log('merchant exists');
                resolve(merchantData.key);
            }else{
                // get merchant unique push ID
                let merchantKey = firebase.database().ref('merchants').push({
                    address : "NTUC"
                }).getKey();
                resolve(merchantKey);
            }
        });
    });
    
    let promiseBranchKey = new Promise((resolve, reject) => {
        firebase.database().ref('merchants').orderByChild('branchAddress').equalTo('Blk 167').once('value', function(snapshot) {
            let branchData = snapshot.val();
            if (branchData){
                console.log('branch exists');
                resolve(branchData.key);
            }else{
                // get branch unique push ID
                promiseMerchantKey.then((merchantKey) => {
                    let branchKey = firebase.database().ref('merchants').child(merchantKey).push({
                        branchName : 'Marsiling',
                        branchAddress : 'Blk 167'
                    }).getKey();
                    resolve(branchKey);
                });
            }
        });
    });
    
    promiseBranchKey.then((branchKey) => { 
        console.log('branchkey' + branchKey); 
        console.log('currencykey' + promiseMerchantKey);
    });
    

    Considering that promise 2 depends on the value resolved by promise 1 you should have the then() method used inside it and causing the resolve of promise 2 to happen only when the first promise already returned value.

    Because resolving of promise 2 can be done only if promise 1 is already resolved there is no need in promise.all() and we can use then on promise 2 to indicate when both of them were processed.