【问题标题】:Using an async function inside a loop在循环中使用异步函数
【发布时间】:2020-11-05 20:46:25
【问题描述】:

我正在使用一个名为 puppeteer 的 javascript 库,我有一个异步函数用于搜索页面内的所有 iframe(和其他内容),如下所示:

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 文件,对于每个站点,我必须使用它的字符串调用前一个函数,例如参数:

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.

我的 file.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(/[\r\n]+/);
            // 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();
  
}

【问题讨论】:

  • 你检查每个web_page 的实际值了吗?好像网址不正确(根据我对错误消息Error: Protocol not supported.的解释)。
  • 是的,值是正确的。我只尝试了一个网站,它可以正常工作。
  • console.log("currentline: "+currentline[1]) 行打印的东西是否正常?如果您在 CSV 中复制该单个工作行(因此它包含标题和两个相同的行)会发生什么?
  • frame.url() 在任何情况下都是有效的网址吗?
  • 并非在所有情况下,在一种情况下我都有:chrome-error://chromewebdata/。但我认为这不是问题,因为它为 x-frame-option 和 csp 的值写入了 undefined。我在终端中没有错误

标签: javascript node.js asynchronous async-await puppeteer


【解决方案1】:

在 for 循环中调用 Promise 并不总是一个好主意。
由于您无法控制应用程序的时间,因此您将自己暴露在奇怪的副作用中。
尝试将您的调用分组到 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 功能。似乎有一个协议错误阻止了您的承诺解决。

【讨论】:

  • 我试过了,但它不起作用。我根据您的想法更改了我的功能,如果您可以尝试在我原始问题的末尾观看我的编辑,我将 check_page 功能的整个代码。
  • 我建议查看 req.open('GET', frame.url(), false); 中的 frame.url()。放一些日志看看url是否正常。
  • 我放了一个控件来检查 url 是否有效,但我遇到了同样的问题,因为该函数只打印 csv 文件最后一个元素的策略。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-03-07
  • 2019-01-17
  • 2018-06-26
  • 2011-12-03
  • 2021-05-02
  • 2017-12-16
  • 1970-01-01
相关资源
最近更新 更多