Где вызвать цикл for для перебора массива значений - PullRequest
0 голосов
/ 04 июня 2018

У меня есть функция javascript, которую я использую для очистки. Я использую ее с Puppeteer.Если я использую одно значение, оно работает, но если я ввожу цикл for для его перебора массива значений, это не удастся.Я хотел бы знать, каким будет правильное место для введения цикла for.

Это мой рабочий базовый скрипт:

const puppeteer = require('puppeteer');
var listOfURLs = [url1, url2,url3,url4,url5]
let scrape = async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(listOfURLs[0]);

  const result = await page.evaluate(() => {
    let title = document.querySelector('#innerLeft > div.dspPropertyTitle > h1').innerText;
    return {
      title
    }

  });

  browser.close();
  return result;
};
scrape().then((value) => {
  console.log(value); 
});

мои URL-адреса содержатся в переменной listOfURLs.Если я вручную ссылаюсь на listOfURLs [0], как в примере выше, он работает просто отлично.Теперь я хочу, чтобы он прошел по всему массиву и имел доступ к значениям в виде listOfURLs [i], поэтому я попробовал это, и это не сработало.Я не знаю, что не так.

const puppeteer = require('puppeteer');    
var listOfURLs = [url1, url2, url3, url4, url5]
for (i=0; i<=listOfURLs.length; i++) {
  let scrape = async () => {
    const browser = await puppeteer.launch({headless: true});
    const page = await browser.newPage();

    await page.goto(listOfURLs[i]);

    const result = await page.evaluate(() => {
      let title = document.querySelector('#innerLeft > div.dspPropertyTitle > h1').innerText;
      return {
        title
      }

    });

    browser.close();
    return result;
  };
  scrape().then((value) => {
    console.log(value); 
  });
}

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

i поднят, а scrape асинхронен - ​​после того, как scrape await с в самом начале, цикл for завершится, поэтому i станет listOfURLs.length + 1, чтоозначает, что доступ к listOfURLs[i] позже не будет работать.

Используйте взамен let, чтобы каждая итерация имела отдельную привязку для i.

Вы также должны проверить i < listOfURLs.length,не i <= listOfURLs.length, потому что i < listOfURLs[listOfURLs.length] будет неопределенным:

for (let i=0; i < listOfURLs.length; i++) {

Но такие циклы for довольно уродливы и часто являются источниками таких проблем - вы могли бы рассмотреть forEach вместо этого,которая имеет лучшую абстракцию, имеет область действия функции (является составной) и не требует ручной итерации, если вы в порядке, отправляя запросы параллельно:

listOfURLs.forEach(async (url) => {
  const scrape = async () => {
    const browser = await puppeteer.launch({headless: true});
    const page = await browser.newPage();
    await page.goto(url);
    const result = await page.evaluate(() => {
      const title = document.querySelector('#innerLeft > div.dspPropertyTitle > h1').innerText;
      return { title };
    });
    browser.close();
    return result;
  };
  scrape().then((value) => {
    console.log(value); 
  });
});

(другой вариант, использующий методы массива - reduce, еслиВы хотите делать запросы в серийном)

0 голосов
/ 04 июня 2018

Ваша проблема, вероятно, связана с тем, что вы делаете асинхронные вызовы внутри цикла for.Вы хотите получить результат, прежде чем переходить к следующему, и, поскольку он асинхронный, ваш код не будет ждать ответа и перейдет к следующему URL-адресу в массиве.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...