2014-11-25 3 views
1

В настоящее время я использую обещания, чтобы предотвратить необходимость вложенных обратных вызовов в моем коде, но я ударил неудачу. В этом случае я использую request-обещание узла и cheerio для эмуляции jQuery на сервере. Однако в какой-то момент мне нужно позвонить jQuery.each(), чтобы создать запрос для каждого элемента <a>. Есть ли способ, которым я могу использовать обещания для предотвращения этого вложенного обратного вызова?Предотвращение вложенных обратных вызовов в 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 
}); 

Благодаря Benjamin Gruenbaum для alterting меня к методу .map() в Блюберд.

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

В качестве альтернативы, вы можете определить действия для одного звена, а затем обработать их. Это будет похоже.

+0

Вам не нужно «Promise.resolve». – SLaks

+0

@SLaks ждут, неважно - да. Хотя они используют Bluebird - они не раскрывают свои методы снаружи (бог знает почему), так что решите _is_. –

+0

Тогда что именно оно возвращается? Кроме того, вам не хватает ')'. – SLaks

Смежные вопросы