Javascript 解析云函数-按顺序执行的代码ot
如果满足某些条件,我有下面的函数来更新行,在for循环的末尾,响应包括更新了多少行。尽管更新了超过零行,但响应显示为零。查看日志,似乎response.success在完成for循环之前触发 为什么会这样Javascript 解析云函数-按顺序执行的代码ot,javascript,parse-platform,parse-javascript-sdk,parse-cloud-code,Javascript,Parse Platform,Parse Javascript Sdk,Parse Cloud Code,如果满足某些条件,我有下面的函数来更新行,在for循环的末尾,响应包括更新了多少行。尽管更新了超过零行,但响应显示为零。查看日志,似乎response.success在完成for循环之前触发 为什么会这样 Parse.Cloud.define("reset", function(request, response) { var isSaveNeeded = false var Query = new Parse.Query("price"); Query.equalTo('i
Parse.Cloud.define("reset", function(request, response) {
var isSaveNeeded = false
var Query = new Parse.Query("price");
Query.equalTo('isActive', true);
Query.find({useMasterKey:true})
.then((results) => {
console.log("Found " + results.length + " price rows")
var currentDate = moment()
var noOfRowsUpdated = 0
for (let i = 0; i < results.length; ++i) {
var valid_till_date = results[i].get('valid_till_date');
if (valid_till_date == null) {
// if user had not selected valid_till_date then set to expire after system max no of days
var updatedAt = results[i].get('updatedAt');
if (currentDate.diff(updatedAt,'days') > 10) {
console.log("Permanent change row to be set inactive. Updated at - " + currentDate.diff(updatedAt)+ updatedAt)
results[i].set('isActive',false)
isSaveNeeded = true
}
} else if (currentDate.diff(valid_till_date) > 0) {
// check whether valid_till_date has passed
console.log("Found row with elapsed valid date " + results[i].id)
results[i].set("isActive",false)
isSaveNeeded = true
}
if (isSaveNeeded == true) {
console.log("Record needs to be saved for " + results[i].id)
results[i].save(null, {useMasterKey:true})
.then(function (user) {
++noOfRowsUpdated
console.log("reset : Object ID: " + results[i].id + " saved - " + noOfRowsUpdated)
})
.catch(function (error) {
console.log("reset : Error saving Object ID: " + results[i].id + error);
response.error(error);
})
} else {
console.log("Record not to be saved for " + results[i].id)
}
isSaveNeeded = false
} // end of for loop
//BELOW IS EXECUTED BEFORE FOR LOOP COMPLETES
console.log("Updated " + noOfRowsUpdated +" price rows");
response.success("Updated " + noOfRowsUpdated +" price rows")
}) // end of .then((results)
.catch(function(error) {
response.error("Failed to fetch from price" + error );
});
});
Parse.com的save是异步运行的,这样循环在保存发生之前就完成了。解决方案是稍微重新组织代码,并在执行响应函数之前等待保存
诀窍是收集数组中每个save返回的承诺,并使用Promise.when同义词Promise.all等待这些承诺的实现
为了更清楚地说明这一点,需要考虑到保存所需的逻辑,因此此云功能只能处理数据库
Parse.Cloud.define("reset", function(request, response) {
var Query = new Parse.Query("price");
Query.equalTo('isActive', true);
Query.find({useMasterKey:true}).then((results) => {
console.log("Found " + results.length + " price rows");
// assuming ES6 or something like underscore
let pricesToSave = results.filter(price => priceNeedsSave(price));
// here's the important part, collect the promise from each save
// proceed only after the promises have completed
let promises = pricesToSave.map(price => price.save(null, {useMasterKey:true}));
return Parse.Promise.when(promises).then(() => pricesToSave.length);
}).then(count => {
response.success("Updated " + count +" price rows");
}).catch(error => {
response.error("Failed to fetch from price" + error );
});
}
为了完整起见,下面是经过分解的needsSave逻辑。OP应该检查一下,我刚刚复制了循环体
function priceNeedsSave(price) {
var isSaveNeeded = false;
var currentDate = moment()
var valid_till_date = price.get('valid_till_date');
if (valid_till_date == null) {
// if user had not selected valid_till_date then set to expire after system max no of days
var updatedAt = price.get('updatedAt');
if (currentDate.diff(updatedAt,'days') > 10) {
console.log("Permanent change row to be set inactive. Updated at - " + currentDate.diff(updatedAt)+ updatedAt)
price.set('isActive',false)
isSaveNeeded = true
}
} else if (currentDate.diff(valid_till_date) > 0) {
// check whether valid_till_date has passed
console.log("Found row with elapsed valid date " + price.id)
price.set("isActive",false)
isSaveNeeded = true
}
return isSaveNeeded;
}
我怀疑async,但不知道如何在javascript代码中处理。我必须说这个“承诺”的概念需要更多的时间去掌握而不是去想!!将尝试您的代码,但有一个问题-results.filterprice=>一次传递一个解析对象以运行是否正确?如果是这样的话,那么就不需要for循环了,对吗?@ashishn,还要注意Parse.Object实现了dirty,所以另一种方法是只更改该函数中的price对象,并根据price.dirty进行过滤。下面是一些关于承诺的提示。虽然Parse有自己的Parse.Promise类,但它们是主干风格的,并且与其他主干风格的Promise兼容,几乎每个服务器调用的API都会使用这些主干风格的Promise。当您使用.then或.always等添加回调时,其结果将沿着承诺链传递。如果它已经包装在承诺中,它将根据需要调用下一个成功或错误处理程序。如果不是,它将自动包装在已解决的承诺中。如果没有返回,则只要到达块的末尾,就会返回一个空的已解析promisegets,即使异步代码仍在运行,并且确实有返回值。确保如果在另一个方法中调用异步方法,则使用return语句等待并返回嵌套承诺的结果。此外,如果您的承诺失败,并且您的.thens只有成功处理程序,那么错误会一直传递到下一个错误处理程序。还请注意,一旦错误处理程序以相同的方式工作,它将返回其值并传递。如果不返回值,它将返回一个空的已解析承诺!这让我很恼火。小心后一个问题,因为它可能会导致意外行为,即您认为自己正在捕获错误,但函数返回success,或者由于链的success处理程序中的下一个链接期望未传递的值而崩溃,因为它从错误处理程序获得了空的已解决承诺。确保你适当地打破了你的外链,或者,更好的是,在你的外链上只有一个错误处理程序,这样任何失败的承诺都会一直被传递下去。