我的承诺是否按预期工作

Are my promises working as intended?

本文关键字:工作 承诺 是否 我的      更新时间:2023-09-26

我正在 Parse 的云代码中编写一个函数,该函数用 5 张扑克牌填充服务器。这个想法是服务器应该等到所有 5 张卡都在数据库中,然后再转到函数的下一部分(目前只是向控制台输出一条消息。

我看到的是所有 5 张卡都被添加到数据库中。它们也不一定按顺序出现在数据库中,这让我相信它们是异步添加的。在大多数情况下,我的日志记录显示了预期的行为。

I2015-01-03T17:08:01.244Z] Attempting to create cards x5
I2015-01-03T17:08:01.245Z] Attempting to save card0
I2015-01-03T17:08:01.247Z] Attempting to save card1
I2015-01-03T17:08:01.248Z] Attempting to save card2
I2015-01-03T17:08:01.249Z] Attempting to save card3
I2015-01-03T17:08:01.250Z] Attempting to save card4
I2015-01-03T17:08:01.352Z] Card saved:4
I2015-01-03T17:08:01.353Z] Card saved:4
I2015-01-03T17:08:01.354Z] Card saved:4
I2015-01-03T17:08:01.355Z] Card saved:4
I2015-01-03T17:08:01.356Z] Card saved:4
I2015-01-03T17:08:01.357Z] ALL 5 Promises theoretically fulfilled

但是,请注意,当实际保存卡时,每个卡的日志都使用相同的数字 - 在本例中为"卡保存:4"。

问题是...我的承诺是否按预期实现?如何修复我的错误以显示保存的实际卡号?

这是我的代码:

Parse.Cloud.define("populateServer", function(request, response)
{
    console.log("Attempting to create cards x5");
    var promises = createCards(5);
    Parse.Promise.when(promises).then(function(result)
    {
        console.log("ALL 5 Promises theoretically fulfilled");
    });
});
function createCards(qty)
{
    var promises = [];
    for (i=0;i<qty;i++)
    {
        var Card = Parse.Object.extend("Card");
        var card = new Card();
        card.set("name", "test");
        card.set("number", i);
        console.log("Attempting to save card" +i);
        var promise = card.save();
        promises.push(promise);
        promise.then(function() {
            console.log("Card saved:" +i);
        }, function(error) {
            console.log("Uh oh, something went wrong.");
        });
    }
    return promises;
}

你实际上得到了你想要的行为,但i在你的承诺结束时总是 4,因为它在任何then处理程序执行之前递增(你的 for 循环是同步的,但你的处理程序是异步的)。

通常传递给all的承诺不会同步解析,但由于您是通过then每个承诺来创建链的,因此您的调用只会在前一个承诺完成后触发。

附带说明一下:我对 Parse 的 promise 实现不是很熟悉,但您可以通过从函数返回 promise 链来节省自己创建一个额外的数组并调用Parse.Promise.when

function createCards(qty) {
      // create a resolved promise that starts the "chain"
      // for Parse prommises use Parse.Promise.as();
      var promiseChain = Parse.Promise.as();
      // start the for loop
      for (i=0;i<qty;i++) {
        // add another promise onto our chain
        // you can `then` or `catch` off of this
        // now if you want
        promiseChain = promiseChain.then(function () {
          // ... any additional logic
          card.save();
        });
      }
      return promiseChain;
}
// usage
createCards(5)
  .then(function () {
    console.log('finished');
  });

正如 Nick 所说,在任何then处理程序执行之前,您的计数器 ( i ) 会增加到 4,因此自然所有处理程序都使用 i 的最终值(即 4)。

解决此问题的最快解决方法可能是将then处理程序的分配包含在闭包中,在该闭包中,您可以使用变量来记住调用闭包时i的值。

例如,替换以下内容:

promise.then(function() {
    console.log("Card saved:" +i);
}, function(error) {
    console.log("Uh oh, something went wrong.");
});

有了这个:

(function(){
    var myIndex = i;
    promise.then(function() {
        console.log("Card saved:" + myIndex);
    }, function(error) {
        console.log("Uh oh, something went wrong.");
    });
})();

我做了几个小提琴来观察行动中的区别: 没有闭合 - 有闭合