От приложения функции с одним аргументом к отображению массива с использованием async/await в узле

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

Я начинаю с очень простой функции скриншота из здесь :

const puppeteer = require('puppeteer');

puppeteer.launch().then(async browser => {
  const page = await browser.newPage();
  await page.goto('https://example.com');
  await page.screenshot({path: 'screenshot.png'});
  await browser.close();
});

Это просто делает один скриншот. Я хотел бы дать ему массив и сделать несколько снимков экрана.

Для моего приложения я немного подправил это с помощью переменной mypage:

const puppeteer = require('puppeteer');
puppeteer.launch().then(async browser => {
  const mypage = 1
  const page = await browser.newPage();
  await page.goto(`https://localhost:9001/${mypage}`);
  await page.screenshot({path: `${mypage}.png`});
  await browser.close();
});

Теперь я хотел бы параметризовать этот список по mypages = [1... 1000]. В старом javascript, используя underscore.js, я бы попробовал что-то вроде:

// define the function
function ss(mypage) {
  puppeteer.launch().then(async browser => {
    const page = await browser.newPage();
    await page.goto(`https://localhost:9001/${mypage}`);
    await page.screenshot({path: `${mypage}.png`});
    await browser.close();
});  
}

// populate the array of pages, eg make var mypages = [1,2,3...1000]
var mypages = [];
for (var i = 1; i <= 1000; i++) {
    mypages.push(i);
}

// call the screenshot function on each page in my pages.
_.each(mypages, ss)

Мне непонятно, как я могу использовать async/await для работы с каждой страницей в mypages (и, возможно, для создания этого массива более идиоматически).

Как я могу переписать свою функцию кукловода, которая работает для mypage = 1, чтобы отображать весь массив mypages?


person Mittenchops    schedule 01.11.2018    source источник
comment
Примечание для будущих читателей: приведенный выше код, скорее всего, приведет к сбою вашей машины, если вы попытаетесь его запустить.   -  person Mittenchops    schedule 02.11.2018


Ответы (1)


Функция скриншота должна быть асинхронной:

 async function screenshot(mypage) {
  const browser = await  puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(`https://localhost:9001/${mypage}`);
  await page.screenshot({path: `${mypage}.png`});
  await browser.close();
}

Затем сделайте один скриншот за другим:

 (async function() {
    for(let i = 0; i < 1000; i++)
      await screenshot(i);
 })();

Или все одновременно (не уверен, что это работает):

 Promise.all(Array.from({ length: 1000 }, (_, i) => screenshot(i)))
  .then(/*...*/);
person Jonas Wilms    schedule 01.11.2018
comment
Однако это открывает 1000 браузеров одновременно. Я бы рекомендовал делать скриншоты последовательно, желательно в пределах одного экземпляра puppeteer. - person Bergi; 02.11.2018
comment
Берги, что-то вроде того, что функция скриншота принимает браузер в качестве аргумента и инициализирует его во внешней асинхронной функции? - person Mittenchops; 03.11.2018