2014-11-25 63 views
1

目前我使用promises来试图防止在我的代码中嵌套回调的需要,但我遇到了挫折。在这种情况下,我使用节点的request-promise和cheerio来模拟服务器上的jQuery。不过,在某些时候,我需要拨打jQuery.each(),为每个元素创建一个请求。有什么方法可以使用promise来防止这种嵌套回调?防止使用迭代的JavaScript中的嵌套回调

request("http://url.com").then(function (html) { 
    var $ = cheerio.load(html); 
    var rows = $("tr.class a"); 
    rows.each(function (index, el) { 

     //Iterate over all <a> elements, and send a request for each one. 
     //Can this code be modified to return a promise? 
     //Is there another way to prevent this from being nested? 

     request($(el).attr("href")).then(function (html) { 
      var $ = cheerio.load(html); 
      var url = $("td>img").attr("src"); 
      return request(url); 
     }) 
     .then(function (img) { 
      //Save the image to the database 
     }); 
    }); 
}); 

回答

0

这是我最终得到的最佳解决方案。我做的一些附带更改包括使用url.resolve来允许相对URL起作用。

var $ = require('cheerio'); 
var request = require('request-promise'); 
var url = require('url'); 

var baseURL = "http://url.com"; 

request(baseURL).then(function (html) { 
    $("tr.class a", html).toArray(); 
}).map(function (el) { 
    return request(url.resolve(baseURL, jq.attr("href"))); 
}).map(function (html) { 
    var src = $("td>img", html).attr("src"); 
    return request(url.resolve(baseURL, src)); 
}).map(function (img) { 
    //Save the image to the database 
}); 

感谢本杰明Gruenbaum用于提示我在青鸟的.MAP()方法。

1

假设蓝鸟许诺(在其他的库代码是相似的):

Promise.resolve(request("http://url.com").then(function (html) { 
    var $ = cheerio.load(html)("tr.class a"); 
})).map(function(el){ // map is `then` over an array 
    return el.href; 
}).map(request).map(function(html){ 
    return cheerio.load(html)("td>img").src; 
}).map(request).map(function(img){ 
    // save to database. 
}); 

或者,也可以定义为一个单一的链接的操作,然后处理这些。它看起来很相似。

+0

你不应该需要'Promise.resolve'。 – SLaks 2014-11-25 15:08:23

+0

@SLaks等着,别介意 - 是的。虽然他们使用蓝鸟 - 他们不会将其方法暴露给外部(上帝知道为什么),因此需要解决这个问题。 – 2014-11-25 15:12:34

+0

那么它究竟返回了什么?此外,你错过了')'。 – SLaks 2014-11-25 15:24:53