我在ExpressJS中有一个简单的REST API,可以将多个页面分阶段放置。页码是动态的。
由于性能的限制,我想在获取多个网页时实现异步承诺,等待所有网页下载完毕,以所需的格式设置它们的短语,然后返回输出。
在我研究了有关诺言和异步的所有内容之后(因为我仍然是异步主题的新手),他们中的大多数告诉我使用Promise.all
,但我只是无法理解它可以正常工作。
GET /xxx
时的当前输出{
username: xxx
parsedHTML: []
}
{
username: xxx
parsedHTML: [
"BUNCH OF ANALYSED HTML",
"BUNCH OF ANALYSED HTML",
"BUNCH OF ANALYSED HTML",
...
]
}
const express = require("express");
const http = require("http");
const fetch = require('node-fetch');
const app = express();
app.get("/:username", (req, res)=>{
const username = req.params.username;
let page = 3; //Will be obtained dynamically. But for now, I'll put a constant here
res.json({
username: username,
parsedHTML: getParsedHTML(username, page),
});
console.log("Page sent")
})
function getParsedHTML(username, page) {
let promises = [];
let analyses = [];
for (var i = 1; i < (page + 1); i++) {
promises.push(fetch(`https://example.com/profile/${username}/?page=${i}`)
.then((c) => c.text()));
// console.log(`Added promise`)
}
Promise.all(promises).then(()=>{
for (let i = 0; i < promises.length; i++) {
let promise = promises[i];
analyses.push(analyse(promise));
}
})
return analyses;
}
function analyse(html){
// Some synchronous analyse stuff here
// Right now it do nothing
return html;
}
app.listen(3000, () => console.log('API listening on port ' + 3000 + '!'))
任何帮助将不胜感激。非常感谢。
答案 0 :(得分:3)
您正在正确调用Promise.all
上的promises
,但是getParsedHTML
函数不在等待,该Promise.all
调用可以解决返回之前。因此,您的res.json
正在立即同步运行,并且返回的analyses
是一个空数组。
取而代之的是返回Promise.all
调用,并确保analyze
的响应(来自Promise.all
的调用)而不是Promise:
return Promise.all(promises).then((responses)=>{
for (let i = 0; i < responses.length; i++) {
let response = responses[i];
analyses.push(analyse(response));
}
}).then(() => analyses);
但是您可以通过映射结果响应数组来显着清理代码:
function getParsedHTML(username, page) {
let promises = [];
for (var i = 1; i < (page + 1); i++) {
promises.push(fetch(`https://example.com/profile/${username}/?page=${i}`)
.then((c) => c.text()));
}
return Promise.all(promises)
.then((responses) => responses.map(analyse));
}
还要确保在发送getParsedHTML
之前等待res.json
等待返回的Promise解析:
app.get("/:username", (req, res)=>{
const username = req.params.username;
let page = 3; //Will be obtained dynamically. But for now, I'll put a constant here
getParsedHTML(username, page)
.then((parsedHTML) => {
res.json({
username,
parsedHTML
});
console.log("Page sent")
});
})