У меня есть простой REST API в ExpressJS, который позволяет фазировать несколько страниц вместе. Номера страниц являются динамическими.
Из-за ограничений производительности я хотел бы реализовать асинхронные обещания при извлечении нескольких веб-страниц, дождаться, когда все они закончат загрузку, произнесят их в нужном формате и вернутся к выходу.
После того, как я исследовал все вещи о обещаниях и асинхронных онлайн (так как я все еще новичок в этой асинхронной теме), большинство из них сказали мне использовать 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 + '!'))
Любая помощь будет оценена. Большое спасибо.
Вы правильно звоните в Promise.all
по promises
, но функция getParsedHTML
не ждет, чтобы Promise.all
вызов Promise.all
перед возвратом. Итак, ваш res.json
запускается немедленно, синхронно, и analyses
, которые возвращаются, представляют собой пустой массив.
Promise.all
этого Promise.all
вызов Promise.all
и убедитесь, что вы analyze
ответы (из вызова Promise.all
), а не обещания:
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
:
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")
});
})
analyse(promise)
. Это точно не выглядит правильно. Вы хотите иметь дело с разрешенными результатами послеPromise.all()
не с обещаниями. Если вы имеете дело с обещаниями, вы должны использовать.then()
для них, чтобы получить результат. Вероятно, нуженPromise.all(promises).then(results => { /* use results array here */})
.