2015-01-03 23 views
0

我正在用Parse's Cloud Code编写一个函数,用5张扑克牌填充服务器。这个想法是,服务器应该等到所有5张卡片都在数据库中,然后才能进入功能的下一部分(目前它只是向控制台输出一条消息。)我的承诺是否按预期工作?

我所看到的是所有5卡被添加到数据库中,也并不一定出现在序列数据库中,这使我相信他们是正确的被异步补充说。而对于mostpart我的记录显示预期行为。

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

回答

2

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

传递给all的通常承诺没有同步解析,但由于您在创建每个承诺的链接时,您的调用只会在前一个承诺完成后触发。

在一个侧面说明:我不是超级熟悉解析的承诺的实现,但你也许可以救自己创建一个额外的数组,并从你的函数只是返回的承诺链调用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'); 
    }); 
+0

谢谢!我不知道如何创建承诺链并在循环中使用它们,这非常有用! –

2

由于Nick说,你的计数器(i)在执行任何then处理程序之前增加到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."); 
    }); 
})(); 

我做了一对夫妇拨弄在行动中看到的区别:Without closure - With closure

+0

谢谢!这看起来很有用,但我不完全理解它。 (function(){})如果它不在promise.then()方法中,它是如何调用的? –

+1

@ mac_55该函数被立即调用,注意函数类似于'(function(){...})()' 。第一对圆括号'(function(){...})'创建一个(匿名)函数,第二对(紧接着)表示它被执行。第一对圆括号实际上是可选的(你也可以编写'function(){...}()'),但是它被用作约定来明确该函数是要立即执行的。谷歌为“JavaScript自我调用功能”,你会发现很多解释,其中一些是很好的。 – abl