对一组元素做多个承诺

我有一个objectIds列表,我想要去不同的集合,并根据每个Id做操作。 我宁愿一个接一个地按顺序执行操作(依次)

var removeOperation = function(objectified){ return Comps.findOne({reviews : objectified}).populate([{ path: "reviews", match : {_id : objectified}}]) } var firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt = function(objectified){ var query = {reviews : objectified}; var update = {$pull : {reviews : objectified}}; var option = {new :true}; return Anon.findOneAndUpdate(query, update, option ); }; var thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt = function(objectified){ var query = {reviews : objectified}; var update = {$pull : {reviews : objectified}}; var option = {new :true}; return User.findOneAndUpdate(query, update, option ); } 

我正在走这条路:

 Promise.mapSeries(arrOfObjectIds, function(e){ return removeOperation(e); }) .then(function(results){ console.log(results); var map = results.map(function(e){ // return e.reviews[0] return e }) console.log("map : ", map) return Promise.resolve(map); }) .then(function(compDocs){ console.log("compDocs: ",compDocs) Promise.mapSeries(compDocs, function(compDoc){ return updateCompAndRemoveReviewFromArray(compDoc) // I know it's not show. It's another promise I use }) }).then(function(returned){ return Reviews.remove({_id : {$in : arrOfObjectIds }}) }) .then(function(){ I wanted to do firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt on the array of object Ids to delete the review from the array. Also if we succesfully removed the array here we should not have to go to the next user promise which deletes a users review since if we deleted in Anon it won't be in User. since there is only one review ID possible per review. }) .then(function(){ //if there was no review pulled from the Anon reviews Array. that means it's in the users review and we should do this promise thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt() }) 

所以也许你可以告诉我如何在一个元素数组上使用mapSeries ,这样它就不会做出任何承诺,而是做出多重承诺。

我们可以做些什么:

 Promise.mapSeries(arrOfObjectIds, function(e){ return removeOperation(e); return firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt(e)// extra credit: check if this was successful (review was pulled). If it wasn't got to next one. return thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt(e) }) 

用简单的语言重述问题:

你有一个ID数组,每个ID依次你要调用三个promise-returns函数ABC ,如下所示:

  • A(id) (无条件)
  • 那么B(id) (无条件)
  • 那么C(id) (有条件地取决于B(id)的结果)

我们可以做些什么:

 Promise.mapSeries(arrOfObjectIds, function(e){ return removeOperation(e); return firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt(e)// extra credit: check if this was successful (review was pulled). If it wasn't got to next one. return thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt(e) }) 

是的,虽然不像build议的代码。

首先,您有关于B报告结果的方式的deviseselect。 这个问题暗示B的结果是“成功”与“失败”的一个例子,但这不是模拟它的唯一方式。

选项1:根据承诺链的成功path提供testing数据

B ,使其返回的承诺将在成功(匿名审查被删除)或预期的失败(匿名审查未被删除)上完成,并通过参数报告结果。

 var B = function(objectified) { var query = {reviews: objectified}; var update = {$pull: {reviews: objectified}}; var option = {new :true}; return Anon.findOneAndUpdate(query, update, option).exec(); }; 

那么你会写:

 Promise.mapSeries(arrOfObjectIds, function(id) { return A(id).then(function() { return B(id); }).then(function(item) { // item will be `null` if B(id) found nothing. return item || C(id); }).catch(function(error) { // If anything went wrong, catch the error and log it. console.log(error); // By not re-throwing the error, the mapseries() is allowed to continue. }); }); 

选项2:在承诺链的故障path下传递testing错误

写下B ,使其回复的承诺将成功,或拒绝预期的失败。

 var B = function(objectified) { var query = {reviews: objectified}; var update = {$pull: {reviews: objectified}}; var option = {new :true}; return Anon.findOneAndUpdate(query, update, option).exec().then(function(item) { return item || Promise.reject(new Error('not found')); }); }; 

那么你会写:

 Promise.mapSeries(arrOfObjectIds, function(id) { return A(id).then(function() { return B(id).catch(function(error) { // Here, you have to discriminate between the "expected error" and any unexpected errors. if(error.message === 'not found') { return C(id); } else { throw error; // unexpected error - rethrow it } }); }).catch(function(error) { // If anything went wrong, catch the error and log it. console.log(error); // By not re-throwing the error, the overall mapseries() is allowed to continue. }); }); 

在这两个选项中:

  • 要返回一个真正的Promise,请在ABC使用.exec() 。 (正如我所了解的Mongoose,没有exec()你得到了一个.then()方法,但不是一个完整的Promise)。
  • 如果您希望整个序列在第一个错误时停止,那么在logging后重新抛出错误,或者完全忽略最后的catch()
  • 可以在条件阶段之前或之后非常简单地添加进一步的无条件阶段。

对我来说,选项2更合乎逻辑,尽pipe我可能会select选项1,因为它更加简单和高效。

你可以使用Array.reduce()来执行你的承诺:

 arrOfObjectIds.reduce(function(promise, objectId) { return promise.then(function(result) { return removeOperation(objectId) .then(firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt) .then(thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt); }); }, Promise.resolve()); 

这将执行removeOperation -> firstCheck.. -> thenCheckremoveOperation -> firstCheck.. -> thenCheck检查数组中的一个项目,然后移动到下一个项目。

can we doe something like:是的,就像那样,除了第一个返回退出函数

所以,你可能会做类似的事情

 Promise.mapSeries(arrOfObjectIds, function(e){ return removeOperation(e) .then(function() { return firstCheckIfAnonHasTheIdInReviewsArrayIfThereDeleteIt(e); }).then(function() { return thenCheckIfUserHasTheIdInReviewsArrayIfThereDeleteIt(e); }) })