我对Node.js很陌生。我对承诺函数和Promise.all
有一个问题。
要么我误解了某个概念,要么我做错了什么。我试着研究这个问题,但没有找到正确的答案。
情况如下。
变量dataBase.fetchForId(customerId).then(function(data){ myNicePdfCreator={ setting1: value1,setting2: value2,createPdf: function(customerId){返回新承诺(函数(解析,拒绝)){setting1 somePdfLibrary.createPdf.then(函数(路径)){解析(路径);},函数(Err){//错误创建pdf拒绝(Err);};},函数(Err){//错误从db拒绝(Err)中提取;}
var myNiceMailSender={ setting1: value1,setting2: value2,sendMail: function(email,path){返回新承诺(函数(解析,拒绝){someMailLibrary.createMail(电子邮件,标题,消息,附件)).then(状态){解析(状态);},函数(Err){拒绝(Err);};} }
我希望对数组中的每个对象都这样做(例如,为每个客户获取一份报告,然后通过电子邮件发送给他们)。我试图想出一个承诺函数,它首先创建pdf,然后发送邮件,然后使用forEach
循环将承诺推送到数组,然后使用Promise.all
制作所有pdf并发送邮件。但是无论我尝试什么,每当我向数组推送承诺时,它都在我使用Promise.all
之前就已经被解析了,即使我只是尝试将这两个承诺函数中的一个推到数组中。
如果我这样做;
var promises=[];
AllCustomers.forEach(customer){
promises.push(myNicePdfCreator.createPdf(customer.id));
});
当我将PDF推送到数组时,会直接创建PDF。我甚至不需要打电话给Promise.all
。
同样,如果我试图将承诺函数推送到发送电子邮件的数组中,邮件就会立即发送。
有人能为我指出正确的方向吗?为什么我的承诺在我把它们推到数组中时会被解决?
是否有更好的方法来创建PDF然后发送电子邮件?
任何帮助,谢谢!
发布于 2019-12-13 05:53:37
我想你想要的是在你开始发送电子邮件之前把所有的pdfs都读出来。正如有人已经说过的,当你调用一个承诺,除非你有一个.then或等待它,它的执行是不会等待的。
const promises=[];
for(const customer of AllCustomers){
promises.push(myNicePdfCreator.createPdf(customer.id));
});
Promise.all(promises).then((paths) => {
// paths is going to have an array with the paths of all the pdfs already generated
});
使用此代码,在Promise.all中将等待生成所有pdfs。所以在那个时候,你可以发邮件。
发布于 2019-12-13 05:57:32
如果您想要创建一系列未解决的、未处理的承诺,为每个客户创建一个报告,然后发送电子邮件给该客户,则如下所示:
const pfuncs = AllCustomers.map(customer => {
return async function() {
const pdfPath = await myNicePdfCreator.createPdf(customer.id);
const status = await myNiceMailSendor.sendMail(customer.email, pdfPath);
return {status, pdfPath};
}
})
这将创建一个函数数组--“createPdf”请求尚未开始运行,它正在等待您调用数组中的每个函数。
当你准备好发送请求时,你会
const results = await Promise.all(pfuncs.map(f => f()));
现在结果是一个看起来像[{status: 200, pdfPath: ''} , {status: 200, pdfPath: ''}, ...]
的数组
发布于 2019-12-13 06:02:16
承诺在声明时被执行。如果您想要“锁定”所有的承诺,直到所有的承诺都定义好为止,您可以将其封装在一个函数中,并且在声明完所有的承诺之后,创建一个循环来执行它。
// Await "a" seconds to finish, reject if "a" o "b" are negative
function myPromiseFunction(a, b) {
return new Promise((res, rej) => {
setTimeout(() => {
if (a < 0 || b < 0) {
rej(0);
} else {
res(a+b);
}
}, a * 1000);
})
}
(() => {
let someData = [{a:2,b:2}, {a:10, b:4}];
// Generate promises in functions
let myPromises = someData.map((v) => {
return () => myPromiseFunction(v.a, v.b);
});
// Execute all
myPromises = myPromises.map((promise) => promise());
// ...
})();
Promise.all
函数只等待完成过程的所有承诺,否则任何承诺都会被拒绝。例如:
所有的承诺都是好的:
// Await "a" seconds to finish, reject if "a" o "b" are negative
function myPromiseFunction(a, b) {
return new Promise((res, rej) => {
setTimeout(() => {
if (a < 0 || b < 0) {
rej(0);
} else {
res(a+b);
}
}, a * 1000);
})
}
(() => {
let someData = [{a:2,b:2}, {a:10, b:4}];
// Generate promises in functions
let myPromises = someData.map((v) => {
return () => myPromiseFunction(v.a, v.b);
});
// Execute all
myPromises = myPromises.map((promise) => promise());
// Await all
Promise.all(myPromises).then(res => {
console.log(res, myPromises);
}).catch(err => {
console.log(err, myPromises);
});
})();
您将在console.log
中打印then
,并将如下所示:
// res: [ 4, 14 ]
// myPromises: [ Promise { 4 }, Promise { 14 } ]
但如果你有一个像这样失败的承诺:
let someData = [{a:10,b:2}, {a:4, b:-4}, {a:2, b:4}];
第二个承诺将被负值拒绝,但第一个承诺不会被解析(10秒结束),因此捕获的输出将是:
// err: 0 (this is the error of the first rejected promise)
// myPromises: [
// Promise { <pending> }, // The rejected promise will not stop the pendings
// Promise { <rejected> 0 }, // The rejected promise
// Promise { 6 }, // A "resolved" or maybe "pending"
// ]
https://stackoverflow.com/questions/59322704
复制相似问题