2016-12-06 69 views
-2

我创建使用Express和请求刮刀。 将一个URL数组传递给请求,然后通过for循环迭代该请求。一旦所有的数据被解析并且所有的数据都被解析了,回调函数就会调用res.send。回报倍数承诺从循环

我想这个转换成承诺,但我相信在for循环我使用不会允许我。如果循环导致问题,是否有另一种方法我可以编码并获得相同的结果?

回调方法

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)} 
}); 

承诺履行尝试

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++; 
     }); 
    } 
} 

回答

1

您需要将这些承诺存储在一个列表中,然后调用Promise.all得到一个承诺的一切:

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)。相反,你应该声明的承诺回调函数外url变量,或与新的let更换var