为什么我的第二个javascript promise调用返回与第一个相同的值?

时间:2019-05-06 14:55:24

标签: javascript es6-promise

嗨,我是javascript新手,最近一直在学习promise。我试图等待网络通话的结果,然后再继续我的逻辑。为此,我认为我需要一个等待网络呼叫结果的承诺。我一直在兑现诺言,并注意到一些我不理解的行为。

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();

因此您可以看到var mybool确定了promise函数的输出。当我运行该程序时,这是输出:

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

有人能解释为什么即使在翻转mybool变量后,第二个callpromise()仍会输出我只希望从mybool = false获得的值吗?

3 个答案:

答案 0 :(得分:5)

承诺不会被“召唤”,而是会被创建。您实际上一次创建mypromise之前创建一次callpromise。到时候,mybool为假。如果要在代码中的特定点创建Promise,或者要创建多个Promise,请在函数内部创建Promise。

答案 1 :(得分:1)

您指定为then函数的第一个参数的函数(通常称为“回调”或“处理程序”),当promise“解析”时将调用该函数,而函数(“回调”,而不是then)是您自己提供的值作为resolve调用的参数。

在您的示例中,fulfilled"PASS"(您指定为pvalue的参数resolve的值)。 fulfilled这个名字在这里似乎不太合适,可能是由于您(错误地)理解了诺言的工作方式。合适的名称为valuepvalue(与resolve承诺的相同)。

但是您缺少的关键难题是,每次使用某个回调函数调用then时,如果promise位于“ resolved”中,则执行回调函数 状态(表示resolve已经被调用过了)。

因此,您可以调用then 1000次,并且您的回调将被调用1000次,并具有一个相同的已解析值(宽松地表示为“承诺”)。

让我们细分您的示例:

  1. 在执行var mypromise = ...;语句时,会创建mypromise Promise,并且已解决 Promise构造函数立即调用提供的函数(在Promise术语中称为“执行者”),并且在您的情况下,该执行器函数立即调用resolve,从而使Promise处于“已解决”状态。

  2. callpromise只是一个函数,当执行该函数时,实质上会导致用户代理在then出现后立即调用作为mypromise的参数提供的函数。 Promise已处于“已解决”状态(请参见1。)。

  3. 您两次调用callpromise,但是即使在第一次调用之前,promise也已被解决,因此就承诺的值而言,mybool的值绝对无效-承诺已经解决了一次,就是这样。

在创建{之前,尝试在promise executor函数(评估console.log的那个)中添加一个mybool调用,并观察一次如何解决您的诺言。 {1}}功能。

答案 2 :(得分:1)

您正在做的最简单的更改可能是将mybool传递给您的诺言创建者,正如其他人指出的那样,它应该是一个函数。

我还要添加一个计数器,以便您可以看到以与创建结果不同的顺序解析/拒绝结果。

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);