从 For 循环返回多个 Promise [英] Return Multiple Promises From For Loop

查看:64
本文介绍了从 For 循环返回多个 Promise的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Express 和 Request 创建一个抓取工具.URL 数组被传递给 request,然后通过 for 循环进行迭代.解析完所有数据并解析所有数据后,回调将调用 res.send.

I'm creating a scraper using Express and Request. An array of URL's is passed to request which is then iterated through a for loop. Once all the data is parsed and all data is resolved the callback calls res.send.

我正在尝试将其转换为 promise,但我相信我使用的 for 循环不允许我这样做.如果循环导致了问题,是否还有其他方法可以对此进行编码并获得相同的结果?

I'm trying to convert this into promises but I believe the for loop I am using will not allow me. If the loop is causing the issue, is there another way I can code this and achieve the same result?

回调方法

    function scrape(callback){
        for(var i = 0; i < urls.length; i++){
            request(urls[i], function(error, response, html){
                if(!error && response.statusCode == 200){
                    // LOAD Cherio (jQuery) on the webpage
                    var $ = cheerio.load(html);
                    try{
                        var name = $(".name").text();
                        var mpn = $(".specs.block").contents().get(6).nodeValue.trim();
                        var jsontemp = {"MPN": "", "Name": "", "PriceList": {}};

                        jsontemp.MPN = mpn;
                        jsontemp.Name = name;
                        // Traverse the DOM to get tr tags and extract info

                        $(".wide-table tbody tr").each(function (i, row) {
                            var $row = $(row),
                                merchant = $row. attr("class").trim(),
                                total = $row.children(".total").text();
                                jsontemp.PriceList[merchant] = merchant;
                                jsontemp.PriceList[merchant] = total;
                        });
                    }
                    catch(err){
                        console.log('Error occured during data scraping:');
                    }

                        list.push(jsontemp);
                }
                else{
                    console.log(error);
                }
            count++;
            callback();
            });
        }
    }
});

scrape(() => {
    console.log(count);
    if(count == urls.length){res.send(list)}
});

Promise 实现尝试

var urls = [
    "http://test.com/",
    "http://test.com/2"
];
var list = [];
var count = 0;

scrape().then((data) => {
            list.push(data)
            if(count == urls.length){res.send(list)}
        })
        .catch(error => console.log(error))


function scrape(){
    for(var i = 0; i < urls.length; i++){
        return new Promise(function (resolve, reject) {

            request(urls[i], function(error, response, html){

            if(!error && response.statusCode == 200){
                var $ = cheerio.load(html);
                try{
                    var name        = $(".name").text();
                    var mpn         = $(".specs.block").contents().get(6).nodeValue.trim();
                    var jsontemp    = {"MPN": "", "Name": "", "PriceList": {}};

                    jsontemp.MPN    = mpn;
                    jsontemp.Name   = name;

                    // TRAVERSING DOM FOR DATA //
                    $(".wide-table tbody tr").each(function (i, row) {
                        var $row = $(row),
                            merchant = $row. attr("class").trim(),
                            total = $row.children(".total").text();
                            jsontemp.PriceList[merchant] = merchant;
                            jsontemp.PriceList[merchant] = total;
                    });
                }
                catch(err){
                    console.log('Error occured during data scraping:');
                }

                    resolve(jsontemp);
            }
            else{
                console.log(error);
                return reject(error);
            }
        count++;
        });
    }
}

推荐答案

你需要将这些 promise 存储在一个列表中,然后调用 Promise.all 来获取所有的单个 promise:

You need to store these promises in a list, and then call Promise.all to get a single promise for everything:

function scrape() {
  var promises = []; // array of promises
  for(var i = 0; i < urls.length; i++) {
    var url = urls[i];
    var promise = new Promise(function(resolve, reject) {
      // ...
    };

    // add to array
    promises.push(promise);
  }

  // return a single promise with an array of the results
  // by using Promise.all
  return Promise.all(promises);
}

此外,在使用 var 时,不要在循环内的函数内使用循环变量(如 i).相反,您应该在 promise 回调函数之外声明一个 url 变量,或者用更新的 let 替换 var.

Also, don't use loop variables (like i) inside a function inside a loop when using var. Instead, you should declare a url variable outside the promise callback function, or replace var with the newer let.

这篇关于从 For 循环返回多个 Promise的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆