2013-03-30 3 views
0

У меня есть код ниже и я пытаюсь получить доступ к массиву all_records после того, как _.each функция завершена. Однако, поскольку это асинхронно, мне было интересно, удалось ли заставить обратный вызов на символы подчеркивания каждый?Работа с асинхронными функциями. Пользовательский обратный вызов?

var request = require('request'), 
    cheerio = require('cheerio'), 
    _  = require('underscore'); 

var all_records = []; 

_.each([0,100], function(start) { 

    var base_url = "http://www.example.com/search?limit=100&q=foobar&start="; 
    var url = base_url + start; 

    request(url, function(err, res, body) { 
    var $ = cheerio.load(body), 
     links = $('#results .row'); 
    $(links).each(function(i, link) { 
     var $link = $(link); 
     var record = { 
     title: $link.children('.title').text().trim() 
     }; 
     all_records.push(record); 
    }); 
    }); 
}); 

// Need to run this once _.each has completed final iteration. 
console.log(all_records); 

ответ

2

Вот простое решение с использованием simple synchronization method:

var count = 101;//there are 101 numbers between 0 and 100 including 0 and 100 
_.each([0,100], function(start) { 

    var base_url = "http://www.example.com/search?limit=100&q=foobar&start="; 
    var url = base_url + start; 

    request(url, function(err, res, body) { 
    var $ = cheerio.load(body), 
     links = $('#results .row'); 
    $(links).each(function(i, link) { 
     var $link = $(link); 
     var record = { 
     title: $link.children('.title').text().trim() 
     }; 
     all_records.push(record); 
     count--; 
     if(count===0){//101 iterations done 
     console.log(all_records); 
     } 
    }); 
    }); 
}); 

Более элегантное решение может быть accomplied с помощью async «ы .parallel метод.

var requests = []; //an array for all the requests we will be making 

for(var i=0;i<=100;i++){ 
    requests.push((function(done){ //create all the requests 
     //here you put the code for a single request. 
     //After the push to all_records you make a single done() call 
     //to let async know the function completed 
    }).bind(null,i));//the bind is that so each function gets its own value of i 
} 
async.parallel(requests,function(){ 
    console.log(all_records); 
}); 
+1

async был способом пойти, но я закончил использовать async.forEach в конце. – fatnic

+0

Отлично, если это решение решило вашу проблему, подумайте о принятии этого ответа. Кроме того, я думаю, вы имели в виду async.each, а не foreach. –

+0

Да, это согласно документам. Хотя forEach работает также. – fatnic

0

async.each заканчивал тем, что легче всего реализовать.

async.each([0,100], function(start) { 
    var base_url = "http://www.example.com/search?limit=100&q=foobar&start="; 
    var url = base_url + start; 

    request(url, function(err, res, body) { 
    var $ = cheerio.load(body), 
     links = $('#results .row'); 
    $(links).each(function(i, link) { 
     var $link = $(link); 
     var record = { 
     title: $link.children('.title').text().trim() 
     }; 
     all_records.push(record); 
    }); 
    }); 
}, function(err){ 
    console.log(all_records); 
}); 
Смежные вопросы