简体   繁体   中英

Why does my 2nd javascript promise call return the same value as the 1st?

Hi I am new to javascript and have recently been learning about promises. I am trying to wait on the result of a network call before moving forward with my logic. To do this I think I need a promise that waits on the network call's result. I have been practicing with promises and noticed some behavior I don't understand.

var mybool = false;

// Promise
var mypromise = new Promise(
    function (resolve, reject) {
        if (mybool) {
            var pvalue = 'PASS';
            resolve(pvalue);
        } else {
            var fvalue = new Error('FAIL');
            reject(fvalue);
        }
    }
);


// call promise
var callpromise = function () {
    mypromise
        .then(function (fulfilled) {
            // yay, you got a new phone
            console.log(fulfilled);
        })
        .catch(function (error) {
            // ops, mom don't buy it
            console.log(error.message);
        });
}

callpromise();
console.log('This will appear first since prev function call is still thinking');
mybool = true;
console.log(mybool);
callpromise();

So as you can see the var mybool determines the output of the promise function. when I run this program this is the output:

"This will appear first since prev function call is still thinking"
true
"FAIL"
"FAIL"

Can someone explain why even after flipping the mybool var the 2nd callpromise() is still outputting a value I would only expect from mybool = false ?

Promises don't get "called", they get created. You create mypromise once, before callpromise gets actually called. By the time, mybool is false. If you want to create a Promise at a specific point in your code, or if you want multiple promises, create the promise inside of a function.

The function ("callback" or "handler" is these are often called) you specify as the first argument to the then function, will be called when the promise "resolves", and the argument to that function (the "callback", not then ) is the value you yourself supplied as argument to the resolve call.

Meaning that in your example, fulfilled is "PASS" (the value of pvalue that you specify as argument to resolve ). The name fulfilled doesn't seem like a good candidate here, perhaps due to how you understood (incorrectly) promises work. A fitting name for it would be value , or pvalue (the same thing you resolve the promise with).

But the crucial piece of puzzle you're missing is that every time you call then with some callback function, the callback function will execute if the promise is in the "resolved" state (meaning that resolve has already been called earlier).

So you can call then 1000 times, and you will get your callback invoked 1000 times, with that one and the same resolved ("promised" in loose terms) value.

Let's break down your example:

  1. By the time the var mypromise = ...; statement is executed, the mypromise promise is created and resolved -- the Promise constructor immediately invokes the provided function (called "executor" in promise terms), and this executor function in your case immediately calls resolve which puts the promise in the "resolved" state.

  2. callpromise is just a function, which, when executed, essentially causes the user agent to call the function provided as argument to then as soon as and if the mypromise promise is in "resolved" state, which it is already (see 1.)

  3. You call callpromise twice, but the promise was already resolved even before the first call, and so the value of mybool is of absolutely no effect as far as the promised value is concerned -- the promise was already resolved once, and that's it.

Try to add a console.log call in the promise executor function (the one evaluating mybool ) and observe how your promise is resolved once , before you even create the callback function.

The simplest change to what you're doing is probably to pass mybool into your promise-creator, which as others have pointed out should be a function.

I'm also adding a counter, so that you can see the results which resolve/reject in a different order than their creation.

 var mypromise = function(mybool, counter) { return new Promise( function (resolve, reject) { if (mybool) { var pvalue = 'PASS-' + counter; resolve(pvalue); } else { var fvalue = new Error('FAIL-' + counter); reject(fvalue); } } ) } // call promise var callpromise = function (mybool, counter) { mypromise(mybool, counter) .then(function (fulfilled) { // yay, you got a new phone console.log(fulfilled); }) .catch(function (error) { // ops, mom don't buy it console.log(error.message); }); } callpromise(false, 1); console.log('This will appear first since prev function call is still thinking'); callpromise(true, 2); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM