检查异步函数是否有一个随机循环完成

Check if async function has a random loop is finished

我正在做一个简单的任务,它将从一个网站获取一些数据并在另一个网站上检查它,所以我成功地获取了数据并创建了一个循环来检查数据的每个值,但问题是因为nodejs 发送所有请求,然后得到响应,这对我来说太糟糕了

  1. 索引的排列方式不正确,这意味着当我检查控制台中的 i 值时,有时会变成 55 然后 2 然后 26 然后 5 - 所以我可以' t 检查循环是否由索引

    完成
  2. 检查条件变得随机,因此无法捕获是否完成以及是否将所有结果推送到数组中

发生的事情是每次条件为真时它都会返回数组的结果,但我不想要这个我想在完成所有检查后得到数组中的所有结果 - 我试图检查因为数组结果不在循环中,但它只从数据中得到 4 或 5,有时什么都不给我,因为所有请求都已发送并且循环已完成,我正在等待响应,所以我无法捕捉到检查是否收到所有响应的正确方法

这是我的代码:

const http = require("http");
const r = require("request");
const $ = require("jquery-jsdom");
var arr = [];
let data_list_req = function() {
    return new Promise((resolve, reject) => {
        r({
            //get the data from this url
            url: "https://example.com/",
            method: "GET"
        }, function(err,resp,htm) {
            resolve(htm)
        })
    })
}
data_list_req().then((response) => {
    let tr =  $($($(response).find("table")[0]).html()).find("tr");
    let data1_list =  tr.find("td:nth-child(2)");
    var data2_list =  tr.find("td:nth-child(1)");
    for(let i = 0, q = 0; i < data2_list.length, q < data1_list.length; i++, q++) {
         if (data1_list[q].innerHTML == "text") {
            //second step get the data code
            let result_page =  "http://example.com/code.php";
            let check =  function() {
                return new Promise( (resolve, reject) => {
                    r({
                        url: result_page,
                        method: "POST",
                        formData: {
                            "list": data2_list[i].innerHTML+":text"
                        }
                    },  function(err,resp,htm) {
                        resolve(htm)
                    })
                })
            }
            check().then((resp) => {
                let proxy_check =  function() {
                    return new Promise( (resolve, reject) => {
                        var code =  $($(resp).find("table").html()).find("tr")[1].getAttribute("code");
                         console.log(code);
                         console.log(data2_list[i].innerHTML+":text")
                         //last step checking the data
                        r({
                            url:  "http://example.com/checkdata.php?data="+data2_list[i].innerHTML+":"+data1_list[q].innerHTML+"&code="+code,
                            method: "GET"
                        },  function(err,resp,htm) {
                             resolve(htm);
                        })
                    })
                }
                proxy_check().then( (checked) => {
                    //data
                    let first_data =  $(checked).find("td")["prevObject"][1].innerHTML;
                    let second_data =  $(checked).find("td")["prevObject"][2].innerHTML;
                    let check_status =  $(checked).find("td")["prevObject"][3].innerHTML;
                     console.log(first_data+":"+second_data)
                     console.log(check_status)
                    if (check_status == "working") {
                        arr.push(first_data+":"+second_data)
                        console.log(arr)
                    }
                })
            })  
        }
    }
})

您需要创建一个变量 requests 来维护代码已提交给事件循环的承诺计数,并且您需要在承诺解决后减少 requests 的计数。一旦计数变为零,您就可以解决承诺。

例如-

const http = require("http");
const r = require("request");
const $ = require("jquery-jsdom");
var arr = [];
let requests = 0;
let data_list_req = function() {
    return new Promise((resolve, reject) => {
        r({
            //get the data from this url
            url: "https://example.com/",
            method: "GET"
        }, function(err,resp,htm) {
            resolve(htm)
        })
    })
}
const data = await new Promise(function (resolve, reject) {
    data_list_req().then((response) => {
        let tr =  $($($(response).find("table")[0]).html()).find("tr");
        let data1_list =  tr.find("td:nth-child(2)");
        var data2_list =  tr.find("td:nth-child(1)");
        for(let i = 0, q = 0; i < data2_list.length, q < data1_list.length; i++, q++) {
         if (data1_list[q].innerHTML == "text") {
            //second step get the data code
            requests++;
            let result_page =  "http://example.com/code.php";
            let check =  function() {
                return new Promise( (resolve, reject) => {
                    r({
                        url: result_page,
                        method: "POST",
                        formData: {
                            "list": data2_list[i].innerHTML+":text"
                        }
                    },  function(err,resp,htm) {
                        resolve(htm)
                    })
                })
            }
            check().then((resp) => {
                let proxy_check =  function() {
                    return new Promise( (resolve, reject) => {
                        var code =  $($(resp).find("table").html()).find("tr")[1].getAttribute("code");
                         console.log(code);
                         console.log(data2_list[i].innerHTML+":text")
                         //last step checking the data
                        r({
                            url:  "http://example.com/checkdata.php?data="+data2_list[i].innerHTML+":"+data1_list[q].innerHTML+"&code="+code,
                            method: "GET"
                        },  function(err,resp,htm) {
                             resolve(htm);
                        })
                    })
                }
                proxy_check().then( (checked) => {
                    //data
                requests--;
                    let first_data =  $(checked).find("td")["prevObject"][1].innerHTML;
                    let second_data =  $(checked).find("td")["prevObject"][2].innerHTML;
                    let check_status =  $(checked).find("td")["prevObject"][3].innerHTML;
                     console.log(first_data+":"+second_data)
                     console.log(check_status)
                    if (check_status == "working") {
                        arr.push(first_data+":"+second_data)
                        console.log(arr)
                    }
                    if(requests === 0){
                        resolve(arr);               
                    }
                })
            })  
        }
        }
    })
}

我很久以前就发布了这个问题并尝试了很多东西但它们没有用但最后我创建了一个递归函数,它将一个一个地遍历数组并等待响应然后在完成所有请求并收到所有响应后,它将 return 最后一个结果作为参数并执行我的函数

我的实际问题在 2 点

  1. 所有请求都是随机发送的,响应也是return随机发送的
  2. 当我遍历数组时,我完成了一个条件,该条件将过滤端口并仅获得 8080 的代理,这会导致新问题

下面是该函数如何工作的示例

const r = require("request");
const jsdom = require("jsdom")
const { JSDOM } = jsdom;

//use Promise to allow the response to be accessed anywhere not just inside request module function
function httpRequest(url, method) {
  return new Promise ((resolve, reject) => {
      r({
        url: url,
        method: method,
      }, function(err, resp, data) {
        resolve(data)
      }) 
  })
}
/*
    @param 1 > holds the object who we will loop through
    @param 2 > holds function who will be executed after the loop is finished and presend the result after scraping through all of the object keys as argument to execute your function after scraping the object
    @param 3, param 4 > they shouldn't get any value they are uses for the recursion operation so the only required is just the first, second parameter
*/
function loop(el, fn, val = [], n = 0) {
  //access object keys as array
  var elKeys = Object.keys(el);
  var valKeys = Object.keys(val);
  //get the key and url of the function
  var url = el[elKeys[n]], k = elKeys[n];

  //codition to stop the function and execute fn param after finishing the loop
  if (elKeys.length !== valKeys.length) {
    httpRequest(url, "GET").then(data => {
      //parse the results as dom object to access elements
      var doc = new JSDOM(data)
      //access title tag
      var title = doc.window.document.getElementsByTagName("title")[0].innerHTML
      console.log(title)

      //add elements for val array for comparison operation
      val.push(title)
      //increment {n} variable to navigate into the next index when re use the function
      n++;
      //recursion function
      loop(el, fn, val, n)
    })
  } else {
    //after finished pass the result as argument and execute my function
    fn(val)
  }
}


var obj = {
    "url 1": "https://example.com/",
    "url 2": "https://www.google.com/",
    "url 3": "https://www.youtube.com/"
}
loop(obj, function(results) {
    console.log(results, "finished")
})

我希望这对某人有帮助