我的承诺是否如预期的那样奏效?
Are my promises working as intended?
我正在 Parse 的 Cloud Code 中编写一个函数,用 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
但是,请注意,当卡片实际保存时,每张卡片的日志都使用相同的编号 - 在本例中为 "Card saved: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,因为它在任何 [=12] 之前递增=] 处理程序执行(您的 for 循环是同步的,但您的处理程序是异步的)。
通常传递给 all
的承诺不会同步解决,但由于您通过 then
ing 每个承诺创建链,您的调用只会在前一个完成后触发。
旁注:我对 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 所说,您的计数器 (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
我正在 Parse 的 Cloud Code 中编写一个函数,用 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
但是,请注意,当卡片实际保存时,每张卡片的日志都使用相同的编号 - 在本例中为 "Card saved: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,因为它在任何 [=12] 之前递增=] 处理程序执行(您的 for 循环是同步的,但您的处理程序是异步的)。
通常传递给 all
的承诺不会同步解决,但由于您通过 then
ing 每个承诺创建链,您的调用只会在前一个完成后触发。
旁注:我对 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 所说,您的计数器 (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