Q.allSettled 没有返回所有结果
Q.allSettled not returning all the results
我正在尝试在 NodeJS (LoopbackJS) 中使用 Q.allSettled 来实现以下场景。
作为我的方法 (REST API
) 的输入,我得到了一个对象数组。这些对象中的每一个在内部都有 2 个对象:ObjA
& ObjB
.
对于数组中的每一项:
如果数据库中存在 ObjA
获取其 ID 并发送邮件 #1
如果不存在则插入ObjA
然后获取其ID并发送邮件#2。
在ObjB
中设置ObjA.ID
并保存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[]
的承诺总数是 4。但是尽管如此,结果数组只包含 1 个项目。
我的代码适用于正常情况,但如果出现错误,例如在发送邮件时,我需要发送它作为回应。这不起作用,因为结果数组不包含电子邮件发送承诺的输出。
有人可以告诉我我做错了什么吗?如果我需要以其他方式处理它?
我找到了一种方法来处理上述情况。但我仍然愿意接受其他方法。
我没有在将第二个承诺添加到 promises
数组后解析 defObjAList
,而是等到所有承诺都添加到数组中。
然后在 allSettled
处理程序(仅监控 1 个承诺)中,我再次通过再次传递 promises
数组(现在包含 4 个承诺)来调用 Q.allSettled
。现在 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
});
});
我正在尝试在 NodeJS (LoopbackJS) 中使用 Q.allSettled 来实现以下场景。
作为我的方法 (REST API
) 的输入,我得到了一个对象数组。这些对象中的每一个在内部都有 2 个对象:ObjA
& ObjB
.
对于数组中的每一项:
如果数据库中存在 ObjA
获取其 ID 并发送邮件 #1
如果不存在则插入ObjA
然后获取其ID并发送邮件#2。
在ObjB
中设置ObjA.ID
并保存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[]
的承诺总数是 4。但是尽管如此,结果数组只包含 1 个项目。
我的代码适用于正常情况,但如果出现错误,例如在发送邮件时,我需要发送它作为回应。这不起作用,因为结果数组不包含电子邮件发送承诺的输出。
有人可以告诉我我做错了什么吗?如果我需要以其他方式处理它?
我找到了一种方法来处理上述情况。但我仍然愿意接受其他方法。
我没有在将第二个承诺添加到 promises
数组后解析 defObjAList
,而是等到所有承诺都添加到数组中。
然后在 allSettled
处理程序(仅监控 1 个承诺)中,我再次通过再次传递 promises
数组(现在包含 4 个承诺)来调用 Q.allSettled
。现在 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
});
});