阻止使用迭代的JavaScript嵌套callback

目前我使用的承诺,以防止在我的代码嵌套callback的需要,但我已经遇到挫折。 在这种情况下,我使用节点的request-promise和cheerio来模拟服务器上的jQuery。 不过,在某些时候,我需要调用jQuery.each()来为每个<a>元素创build一个请求。 有没有什么办法可以使用promise来防止这种嵌套的callback?

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

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

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

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

这是我得到的最好的解决scheme。 我做的一些附带的更改包括使用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 }); 

感谢Benjamin Gruenbaum在蓝鸟中将我指向.map()方法。