Отображение массива с использованием Async / Await с Puppeteer для возврата результата - PullRequest
0 голосов
/ 16 октября 2018

Я новичок в работе с асинхронным программированием, поэтому может быть что-то простое, что я упускаю здесь.

У меня есть экспресс-проект, я передаю массив в теле моегоrequest.

Внутри моей функции я проверяю тело, затем анализирую массив и использую обещание при отображении в массив.

const games = JSON.parse(JSON.stringify(req.body.games));

const gamesMap = games.map((game) => gameSearch(game));

return Promise.all(gamesMap)
    .then(function(g) {
        // async is still running here, I want to wait until it returns 
        console.log(g); // returns [ undefined, undefined, ... ]
    });

Функция поиска игры использует puppeteer для использованиябезголовый браузер для возврата цен игры, переданной в массиве.Однако, он не ждет, пока массив не будет возвращен, прежде чем вызывается Promise.all, поэтому console.log(g); выше возвращает неопределенный массив.Я предполагаю, что это как-то связано с использованием async await внутри функции gameSearch, хотя я не уверен, что мне здесь делать?Любая помощь будет принята с благодарностью.

function gameSearch(game) {
  (async () => {
    const url = '.....' + game;
    try {
      const browser = await puppeteer.launch();
      const page = await browser.newPage();
      await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36');
      await page.goto(url);
      const selector = '.searchRcrd';
      await page.waitForSelector(selector);

      const searchRcrds = await page.$$(selector);

      const records = [];

      for (let i = 0; i < searchRcrds.length; i++) {
        const searchRcrd = searchRcrds[i];
        const title = await searchRcrd.$eval('h1', (h1) => h1.innerText.trim());
        const buyFor = await searchRcrd.$eval('.desc .prodPrice div:nth-child(2) .priceTxt:nth-child(1)', (buy) => buy.innerText.trim());
        const inStoreFor = await searchRcrd.$eval('.desc .priceTxt:nth-child(2)', (inStore) => inStore.innerText.trim());
        const imgSrc = await searchRcrd.$eval('div.thumb > a > img', (img) => img.src.trim());

        records.push({
          'title': title,
          'buyFor': buyFor,
          'inStoreFor': inStoreFor,
          'imgSrc': imgSrc
        });
      }

      await browser.close();

      return records;
    } catch (err) {
      next(err);
    }
  })();
}

1 Ответ

0 голосов
/ 17 октября 2018

return records возвращается из (async () => {…})(); IIFE.Отбросьте это и сделайте gameSearch самим async function, который возвращает (обещание) массив.

async function gameSearch(game) {
  const url = '.....' + game;
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36');
  await page.goto(url);
  const selector = '.searchRcrd';
  await page.waitForSelector(selector);

  const searchRcrds = await page.$$(selector);

  const records = [];

  for (let i = 0; i < searchRcrds.length; i++) {
    const searchRcrd = searchRcrds[i];
    const title = await searchRcrd.$eval('h1', (h1) => h1.innerText.trim());
    const buyFor = await searchRcrd.$eval('.desc .prodPrice div:nth-child(2) .priceTxt:nth-child(1)', (buy) => buy.innerText.trim());
    const inStoreFor = await searchRcrd.$eval('.desc .priceTxt:nth-child(2)', (inStore) => inStore.innerText.trim());
    const imgSrc = await searchRcrd.$eval('div.thumb > a > img', (img) => img.src.trim());

    records.push({
      'title': title,
      'buyFor': buyFor,
      'inStoreFor': inStoreFor,
      'imgSrc': imgSrc
    });
  }

  await browser.close();

  return records;
}
...