目前我使用promises试图阻止我的代码中嵌套回调的需要,但我遇到了挫折。在这种情况下,我使用node的request-promise和cheerio来模拟服务器上的jQuery。但是,在某些时候我需要调用jQuery.each()
来为每个<a>
元素创建一个请求。有什么方法可以使用promises来阻止这种嵌套回调吗?
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 :(得分:1)
假设Bluebird承诺(其他库中的代码类似):
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.
});
或者,您可以为单个链接定义操作,然后处理这些操作。它看起来很相似。
答案 1 :(得分: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
});
感谢Benjamin Gruenbaum将我改为bluebird中的.map()方法。