【问题标题】:Why does my 2nd javascript promise call return the same value as the 1st?为什么我的第二个 javascript 承诺调用返回与第一个相同的值?
【发布时间】:2019-05-06 23:15:33
【问题描述】:

您好,我是 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 var 之后,2ndcallpromise() 仍然输出我只能从mybool = false 得到的值吗?

【问题讨论】:

  • 作为其他在 HTTP 请求中苦苦挣扎的人的旁注,内置的 XMLHttpRequest 有一个易于使用的异步/同步切换参数,您可以翻转而不是弄乱您自己的自定义承诺链. request.open('GET', 'https://ghibliapi.herokuapp.com/films', true) ^ async request.open('GET', 'https://ghibliapi.herokuapp.com/films', false) ^ synchronus(IE 线程在此 HTTP 请求通过/失败之前不会继续)

标签: javascript es6-promise


【解决方案1】:

Promise 不会被“调用”,它们会被创建。在callpromise 被实际调用之前,您创建一次mypromise。到那时,mybool 是假的。如果您想在代码中的特定点创建 Promise,或者如果您想要多个 Promise,请在函数内部创建 Promise。

【讨论】:

  • 哦,我明白了。谢谢。将我的承诺放在像 function genPromise(){ var mypromise = new Promise( function (resolve, reject) { if (mybool) { var pvalue = 'PASS'; resolve(pvalue); } else { var fvalue = new Error('FAIL'); reject(fvalue); } } ); return mypromise } 这样的函数中解决了这个问题。
  • 我喜欢“承诺不会被“称为”部分,仅此一项就可以帮助任何迷失在承诺中的人。
【解决方案2】:

对您所做的最简单的更改可能是将mybool 传递给您的promise-creator,正如其他人指出的那样,它应该是一个函数。

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

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

【讨论】:

    【解决方案3】:

    您指定为then 函数的第一个参数的函数(“回调”或“处理程序”通常被调用)将在承诺“解决”时被调用,而 函数(“回调”,而不是 then)是 自己作为参数提供给 resolve 调用的值。

    这意味着在您的示例中,fulfilled"PASS"(您指定为 resolve 的参数的 pvalue 的值)。 fulfilled 这个名字在这里似乎不是一个好的候选人,这可能是由于你如何理解(错误地)承诺的工作。它的合适名称是 valuepvalue(与您的承诺相同的名称 resolve)。

    但是您缺少的关键难题是,每次您使用回调函数调用then 时,如果promise 处于“已解决”状态,回调函数执行(意味着resolve 已经被之前调用过)。

    因此,您可以调用 then 1000 次,您的回调将被调用 1000 次,并且具有相同的已解决(松散术语中的“承诺”)值。

    让我们分解你的例子:

    1. var mypromise = ...; 语句被执行时,mypromise 承诺被创建——Promise 构造函数立即调用提供的函数(称为“执行程序”在承诺条款中),并且在您的情况下,此执行程序函数会立即调用resolve,这会将承诺置于“已解决”状态。

    2. callpromise 只是一个函数,它在执行时基本上会导致用户代理调用作为参数提供给then 的函数,如果mypromise 承诺处于“已解决”状态状态,它已经是(参见 1.)

    3. 你调用callpromise 两次,但承诺甚至在第一次调用之前就已经解决了,所以mybool 的值就承诺的值而言绝对没有影响——承诺已经解决了一次,就这样。

    在你创建callback 函数之前,尝试在promise executor 函数(评估mybool)中添加一个console.log 调用,并观察你的promise 是如何解决的一次

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多