我正在尝试用NodeJS异步生成PNG。
async generateAnnualPNG(recap) {
let promises = [];
console.log("Generating images for annual reports")
for (const meter of recap.meters) {
const url = process.env.BASE_URL + "operations/" + recap.operation.name + "/meters/" + meter.prm + "/annual_individual_report";
promises.push(this.makePngScreenshot(recap, url, meter.prm, "annual_2019-2020"));
}
return promises
},用makePngScreenshot
async makePngScreenshot(recap, url, meterId, filename) {
axios.get(url, null); // Make the request to generate html page
const destination = "public/images/" + recap.operation.name + "/" + recap.date_ini + "_" + recap.date_end + "/" + meterId
return new Pageres({ delay: 2, filename: filename })
.src(url, ['1300x650'], { crop: true })
.dest(destination)
.run()
}当我调试时,我可以看到返回的承诺似乎没有问题,它是一个由7个挂起的承诺组成的数组。
我称它为:
module.exports = {
async generatePNGs(recap) {
let promises = [];
promises = this.generateAnnualPNG(recap)
await Promise.all(promises);
console.log("Done generating images")
},我从没见过Done generating images留言..。为什么?
这是日志:
Generating images for annual reports
images.js:53
(node:571426) UnhandledPromiseRejectionWarning: TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
at Function.all (<anonymous>)
at Object.generatePNGs (/home/julien/Code/customer_recap/images.js:17:34)
at init (/home/julien/Code/customer_recap/index.js:113:44)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
<node_internals>/internal/process/warning.js:32
(node:571426) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
<node_internals>/internal/process/warning.js:32
(node:571426) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.发布于 2020-10-13 23:22:00
在promises generatePNGs 中的实际上不是一个数组,它是一个 Promise<Array>**.**,您可以等待它,但是您可能应该从generateAnnualPNG中删除async。
async makePngScreenshot(recap, url, meterId, filename) {
/* ... */
return new Pageres(/*...*/).src(/*...*/).dest(/*...*/).run()
}makePngScreenshot是async,因此它绝对返回一个Promise。
async generateAnnualPNG(recap) {
let promises = [];
/* ... */
for (const meter of recap.meters) {
const url = /* ... */
promises.push(this.makePngScreenshot(/* ... */));
}
return promises
}generateAnnualPNG也是async,所以它绝对会返回一个承诺。显然,该承诺将解析为一组承诺,因为它填充了makePngScreenshot返回的对象的数组。
这意味着,尽管您将promises设置为一个数组,但实际上您已经将其设置为一个承诺。
async generatePNGs(recap) {
let promises = []; // this was an array
promises = this.generateAnnualPNG(recap) // but now it's a promise
await Promise.all(promises);
console.log("Done generating images")
}你最好的选择是将async从generateAnnualPNG的定义中删除。尽管它正在处理承诺,但它并不是在执行任何承诺,到那时,generateAnnualPNG将返回一系列承诺,而不是(承诺)数组的承诺。该列表将按generatePNGs预期的方式工作,您可以像上面那样将该数组直接传递到Promise.all中。
作为另一种选择,您还可以将generatePNGs更改为await this.generateAnnualPNG(/* ... */),只有在您的列表还没有同步准备好(也就是说,您不知道返回的列表中有多少承诺)时,才需要这样做。在这一点上,返回一系列承诺的价值非常小;您可以在await promises中使用generateAnnualPNG,这样generateAnnualPNG的返回值就是对一个值数组的承诺。唯一不这样做的原因是,如果您有UI或日志记录,它将从显示增量进度中获益。
最后注意:看起来makePngScreenshot也是async,实际上没有任何await。如果这是当前代码中的错误,请不要忘记在需要时添加await (例如,添加到axios.get调用中)。
https://stackoverflow.com/questions/64335066
复制相似问题