Использование асинхронной функции внутри цикла

#javascript #node.js #asynchronous #async-await #puppeteer

#javascript #node.js #асинхронный #async-ожидание #кукловод

Вопрос:

Я использую библиотеку javascript с именем puppeteer, у меня есть асинхронная функция для поиска всех фреймов внутри страницы (и других вещей), подобных этому:

 function check_page(web_page){
    (async () => {
        const browser = await puppeteer.launch();
        const page = await browser.newPage();
        await page.goto(web_page);
       
        /*.   my code  */

        await browser.close();

  
})();
}
  

У меня есть другая функция, которую я использовал для чтения csv-файла со списком самых популярных веб-сайтов, для каждого сайта я должен вызвать предыдущую функцию со строкой параметра it like:

 function readCSV(csv){

  var lines=csv.split("n");
  var result = [];
  var headers=lines[0].split(",");
  for(var i=0;i<lines.length;i  ){
      //console.log("lines: " lines[i])
      var obj = {};
      var currentline=lines[i].split(",");
      console.log("currentline: " currentline[1])  
      check_page("https://www." currentline[1]). // pass the site to the function like: https://www.itsname...
      
  }

}
  

Но это не работает.
Иногда это работает для последнего веб-сайта в списке, но в целом выдает эту ошибку:

 UnhandledPromiseRejectionWarning: Error: Protocol not supported.
at exports.XMLHttpRequest.send (/Users/francesco/node_modules/xmlhttprequest/lib/XMLHttpRequest.js:299:15)
at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:1228) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1228) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  

Мой файл.js имеет следующую структуру:

 const puppeteer = require('puppeteer');

const fs = require('fs')
const fileContents = fs.readFileSync('./popular_website.csv').toString()
function readCSV(csv){
     // previous code
}
function check_page(web_page){
    // previous code
}
readCSV(fileContents) 
  

Редактировать:
Я меняю свою функцию, но она не работает, она работает только на последнем веб-сайте. Я публикую всю функцию целиком:

 async function check_page(web_page){

    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(web_page)
    
    /* I search every iframe tag inside web-page and then I send a request for eachone of that for reading csp and x-frame-option from the header*/
    for (const frame of page.mainFrame().childFrames()){

      
      if(frame.url().toString() == "about:blank"){
        console.log("blank")
      }
      else{
        /* I  send for every iframe an http request for retrieve the policies from http header */
        var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;       
        var req = new XMLHttpRequest();
        req.open('GET', frame.url(), false);
        //req.send(null)
        var headers = req.getAllResponseHeaders().toLowerCase();       
        var arr = headers.trim().split(/[rn] /);
            // Create a map of header names to values
            var headerMap = {};
            arr.forEach(function (line) {
              var parts = line.split(': ');
              var header = parts.shift();
              var value = parts.join(': ');
              headerMap[header] = value;
            });
        console.log("policy of:" frame.url());
        console.log("CSP: " headerMap["content-security-policy"]);
        console.log("x-frame-options: " headerMap["x-frame-options"]);
        console.log("-----------------------------------------------------------------")
      }    
    } 
    await browser.close();
  
}
  

Комментарии:

1. Вы проверили фактическое значение каждого web_page из них? Похоже, URL неверен (согласно моей интерпретации сообщения об ошибке Error: Protocol not supported. ).

2. Да, значение правильное. Я пробовал только с одним веб-сайтом, и он работает правильно.

3. console.log("currentline: " currentline[1]) Печатает ли строка нормальные вещи? Что произойдет, если вы продублируете эту единственную рабочую строку в своем CSV (чтобы она содержала заголовок, а затем две идентичные строки)?

4. Является frame.url() ли допустимый URL в каждом случае?

5. Не во всех случаях, в одном случае у меня есть: chrome-ошибка://chromewebdata/. Но я не думаю, что это проблема, потому что он записывает undefined для значений x-frame-option и csp. У меня нет ошибок в терминале

Ответ №1:

Вызов promise в цикле for не всегда является хорошей идеей.
Вы подвергаете себя странным побочным эффектам, поскольку не контролируете время работы своего приложения.
Попробуйте сгруппировать ваши вызовы в Promise.all():

 async function check_page(web_page){
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto(web_page);
       
  /*.   my code  */

  await browser.close();
}

function readCSV(csv){

  var lines=csv.split("n");
  var result = [];
  var headers=lines[0].split(",");
  Promise.all(
    lines.map(line => {
      var obj = {};
      var currentline = line.split(",");
      console.log("currentline: " currentline[1])  
      return check_page("https://www." currentline[1])
    })
  ).then(() => console.log('It worked')).catch(err => /* catch any error in Promise.all*/);
}
  

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

Комментарии:

1. Я пытался, но это не сработало. Я изменил свои функции в соответствии с вашей идеей, если вы можете попробовать посмотреть мое редактирование в конце моего первоначального вопроса, я поместил весь код функции check_page .

2. Я бы рекомендовал проверить frame.url() в req.open('GET', frame.url(), false); . Поместите несколько журналов, чтобы проверить, в порядке ли URL-адреса.

3. Я помещаю элемент управления, чтобы проверить, действителен ли URL-адрес, но у меня та же проблема, потому что функция печатает только политику последнего элемента файла csv.