简体   繁体   English

我的诺言是否如预期般运作?

[英]Are my promises working as intended?

I'm writing a function in Parse's Cloud Code which populates the server with 5 playing cards. 我正在Parse的Cloud Code中编写一个函数,该函数用5张扑克牌填充服务器。 The idea being that the server should wait until all 5 cards are in the database before moving on to the next part of the function (which currently just outputs a message to the console. 这个想法是服务器应该等到所有5张卡都在数据库中之后,才能继续进行功能的下一部分(当前该功能仅向控制台输出一条消息)。

What I'm seeing is that all 5 cards are being added to the database. 我看到的是所有5张卡都已添加到数据库中。 They also do not necessarily appear in the database in sequence, which makes me believe they are correctly being added asynchronously. 它们也不一定按顺序出现在数据库中,这使我相信可以正确地异步添加它们。 And for the mostpart my logging shows intended behaviour. 在大多数情况下,我的日志记录显示了预期的行为。

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

However, notice that when the cards are actually saved, the log for each one of them is using the same number - in this case "Card saved:4". 但是,请注意,当实际保存卡时,每个卡的日志都使用相同的编号-在这种情况下为“已保存卡:4”。

Question is... are my promises working as intended? 问题是...我的诺言是否如预期般运作? and how do I fix my bug to show the actual card number that was saved? 以及如何解决我的错误以显示已保存的实际卡号?

Here's my code: 这是我的代码:

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

You actually are getting the behavior you desire, but i is always 4 at the end of your promises because it is incremented before any of the then handlers execute (your for loop is synchronous but your handlers are asynchronous). 您实际上正在获得所需的行为,但是在您的诺言结束时i总是4,因为它在任何then处理程序执行之前就递增了(您的for循环是同步的,但是您的处理程序是异步的)。

Normally promises passed to all are not resolved synchronously, but since you are creating a chain by then ing of each promise your calls will only fire after the preceeding one has completed. 通常,传递给all诺言不会同步解决,但是由于您是通过then创建每个诺言来创建链的, then您的调用只会在前一个诺言完成后才触发。

On a side note: I am not super familiar with Parse's promise implementation, but you can probably save yourself creating an extra array and calling Parse.Promise.when by just returning the promise chain from your function: 附带一提:我对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');
  });

As Nick said, your counter ( i ) is incremented up to 4 before any of the then handlers execute, so naturally all handlers use the final value of i (which is 4). 正如Nick所说,在任何then处理程序执行之前,您的计数器( i )都会递增至4,因此自然所有处理程序都会使用i的最终值(即4)。

The quickest workaround around this issue is probably to enclose the assignation of the then handler in a closure, in which you can use a variable to remember the value of i at the time the closure was called. 解决此问题的最快解决方法可能是将then处理程序的分配封装在一个闭包中,在该闭包中,您可以使用变量来记住调用闭包时的i值。

For example, replace this: 例如,替换为:

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

With this: 有了这个:

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

I've made a couple fiddles to see the difference in action: Without closure - With closure 我做了几个小提琴,以观察动作的不同: 不闭合 - 闭合

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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