Как дождаться разрешения Обещаний в ExpressJS?

1

Фон:

У меня есть простой 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 + '!'))

Любая помощь будет оценена. Большое спасибо.

Теги:
express
promise

1 ответ

3
Лучший ответ

Вы правильно звоните в 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")
    });
})
  • 0
    Ваш первый блок кода вызывает analyse(promise) . Это точно не выглядит правильно. Вы хотите иметь дело с разрешенными результатами после Promise.all() не с обещаниями. Если вы имеете дело с обещаниями, вы должны использовать .then() для них, чтобы получить результат. Вероятно, нужен Promise.all(promises).then(results => { /* use results array here */}) .
  • 0
    Большое спасибо!! Эта проблема застряла у меня на несколько часов :(
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню