Неожиданное возвращение асинхронной / ожидающей функции - PullRequest
1 голос
/ 09 марта 2019

У скребка, который я делаю, есть маршрут регистрации, чтобы начать процесс очистки.Поскольку процесс очистки занимает очень много времени, я решил создать другой маршрут, по которому мой интерфейс каждые 15 секунд будет запрашивать данные.Проблема, с которой я сталкиваюсь, состоит в том, что маршрут для получения данных возвращает пустой объект, даже когда чистка завершена.В действительности, он должен был вернуть очищенные данные и НЕ возвращать ошибку 404 (см. Код ниже).Я добавил дополнительный код на случай, если это является причиной проблемы.

const scraper = async (email, password) => {
  let grades = [[], [], [], []];
  let category_weights = [];
  try {
    // try to scrape website
    // this block of code contains await functions
  } catch (e) {
    console.log(e);
    return;
  } finally {
    return {
      grades,
      category_weights
    };
  }
};

let result;

app.post("/api/register", (req, res) => {
  result = scraper(req.body.email, req.body.password);
  res.sendStatus(200);
});

app.get("/api/data", (req, res) => {
  console.log(result["grades"]); // undefined
  console.log(JSON.stringify(result, null, 4)); // {}
  result.hasOwnProperty("grades") ? res.json(result) : res.sendStatus(404);
});

1 Ответ

1 голос
/ 09 марта 2019

Код возвращает код состояния 404 , поскольку result является Promise и не имеет свойства grades.

Вы должны ждать, пока обещание не будет выполнено. Вы можете использовать await для этого. Таким образом, как только скребок будет готов, вызовы /api/data вернут данные вместо кода состояния 404 .

Чтобы избежать проблемы тайм-аута, вы можете либо увеличить тайм-аут для этого конкретного маршрута:

req.setTimeout(1000 * 60 * 5); // or whatever value you want

Или просто завершите запрос, как только нажмете /api/register, а затем запустите функцию скребка, ожидая результата.

app.post("/api/register", async(req, res) => {

    res.sendStatus(200);

    try {
        result = await scraper(req.body.email, req.body.password);

    } catch(e) {
        console.log('Scraper failed');
    }

});

app.get("/api/data", (req, res) => {
  console.log(result["grades"]); // undefined
  console.log(JSON.stringify(result, null, 4)); // {}
  result.hasOwnProperty("grades") ? res.json(result) : res.sendStatus(404);
});

И вот доказательство того, что JSON.stringify на Promise вернет {}

console.log(JSON.stringify(new Promise(() => {}), null, 4)); // {}
...