我正在尝试在NodeJS(LoopbackJS)中使用Q.allSettled来实现以下场景。
作为我的方法(REST API
)的输入,我得到了一个对象数组。这些对象中的每一个在内部都有两个对象:ObjA
& ObjB
。
对于数组中的每个项目:
如果数据库中存在ObjA
,请获取其ID并发送邮件#1
如果它不存在,则插入ObjA
然后获取其ID并发送邮件#2。
在ObjA.ID
中设置ObjB
并保存ObjB
。
保存所有对象并发送电子邮件后,发送REST API
电话的响应。如果以前的任何任务失败,请在响应中添加错误详细信息。
以下是伪代码:
myModel.myMethod = function(input, cb){
var defResp = Q.defer();
var promises = [];
try {
var defObjAList = Q.defer();
promises.push(defObjAList.promise);
getObjAIfItExists(input).done(function(inputWIds) { // input[] with IDs populated
inputWIds.forEach(function(item){
var defObjA = Q.defer();
if(item.objA.id){ // objA already exists in DB
var options = { ... }; // options for sending mail #1
promises.push(Q.ninvoke(Email, "send", options)); // using loopback Email which internally uses nodemailer
defObjA.resolve(item.objA.id);
} else {
Q.ninvoke(ObjA, "save", item.objA).done(function (savedA) {
var options = { ... }; // options for sending mail #2
promises.push(Q.ninvoke(Email, "send", options)); // using loopback Email which internally uses nodemailer
console.log(promises.length); // prints 3
defObjA.resolve(savedA.id);
}, function(err){
defResp.reject(err);
});
}
var defObjB = Q.defer();
promises.push(defObjB.promise);
defObjA.promise.done(function(objAId){
item.objB.objAId = objAId;
promises.push(Q.ninvoke(ObjB, "save", item.objB));
console.log(promises.length); // prints 4
}, function(err){
defResp.reject(err);
});
console.log(promises.length); // prints 2
defObjAList.resolve("Process Complete");
}); // inputWIds.forEach
}, function(err){
defResp.reject(err);
}); //getObjAIfItExists
console.log(promises.length); // prints 1
Q.allSettled(promises).done(function (results) {
console.log(results.length); // prints 1
console.log(JSON.stringify(results)); // prints result[] with single item
var response = {};
response.errors = [];
// iterate on results and check if any promise was failed, if yes add the reason to errors array
defResp.resolve(response);
});
} catch (err) {
defResp.reject(err);
}
return defResp.promise.nodeify(cb);
}
出于测试目的,我的输入数组只包含一个项目。因此,添加到promises[]
的promises总数为4.但是尽管如此,结果数组只包含1个项目。
我的代码适用于正常情况,但如果出现错误,例如在发送邮件时,我需要发送邮件作为回应。这是行不通的,因为结果数组不包含电子邮件发送承诺的输出。
有人能告诉我我做错了什么吗?如果我需要以其他方式处理它?</ p>
答案 0 :(得分:0)
我找到了处理上述情况的方法。但我仍然愿意接受替代方法。
在向defObjAList
数组添加第二个承诺后,我没有解析promises
,而是等到所有承诺都添加到数组中。
然后在allSettled
处理程序(仅监视1个promise)中,我再次通过传递Q.allSettled
数组(现在包含4个promise)来调用promises
。现在,allSettled
的第二个处理程序获取结果数组,其中包含4个项目,用于添加的所有承诺。
或者,我可以简单地等待defObjAList
承诺履行,然后致电Q.allSettled
以了解其余的承诺。这在性能方面会更好。但目前我已拨打2次电话Q.allSettled
。
:
:
inputWIds.forEach(function(item, ind){ // added ind param
// handle ObjA
var defObjB = Q.defer();
promises.push(defObjB.promise);
defObjA.promise.done(function(objAId){
item.objB.objAId = objAId;
promises.push(Q.ninvoke(ObjB, "save", item.objB));
console.log(promises.length); // prints 4
if(ind == inputWIds.length-1){ // check if its the last iteration
defObjAList.resolve("Process Complete");
}
}, function(err){
defResp.reject(err);
});
console.log(promises.length); // prints 2
// defObjAList.resolve("Process Complete"); - removed from here
}); // inputWIds.forEach
:
:
Q.allSettled(promises).done(function (resultsOld) {
Q.allSettled(promises).done(function (results) {
console.log(results.length); // prints 4
// handle results array and send response
});
});