[英]Node.js Async waterfall() callback was already called
我從昨天開始在 node.js 上使用async
模塊來處理異步任務的順序。 下面的代碼有效,但錯誤:
回調已被調用
顯示大約 1 到 5 次。 我不知道問題出在哪里,也許getNewsTitles()
上的forEach
循環中的回調getNewsTitles()
調用一次。 所以我把console.log
放在這里,但是無論是否顯示錯誤,這個日志只打印一次。
async.waterfall([
function(callback) {
callback();
},
function(callback) {
// When error, below log doesn't show.
console.log('getting news titles...');
getNewsTitles(arr_uri, arr_subs, function() {
// * The problem is here => "Callback was already called"
callback(null);
});
}
], function(err, result) {
if (err) return next();
else res.send(arr_subs);
});
function getNewsTitles(targets, subs, callback) {
targets.forEach(function(current, index) {
request.get({
uri: current,
encoding: null
}, function(err, response, body) {
if (!err && response.statusCode == 200) {
var $ = cheerio.load(iconv.decode(body, 'EUC-KR'));
var subject = $('.articleSubject a');
for (var i = 0; i < subject.length; i++) {
subs.push(subject[i].attribs.title);
}
if (subs.length == (targets.length - 2) * 20 + 2) {
// when error or not, below log shows one time.
console.log('doubt here too');
callback();
}
}
});
})
}
我錯過了什么..?
request.get() 是一個異步調用。 常規for循環不起作用。 在上面的代碼中,每次成功的 request.get() 都會調用 callback()。 您需要一些可以控制流程的東西,例如 async.each()、async.eachLimit()、async.eachSeries() 等,以便 callback() 只調用一次。
我建議在這種情況下使用 async.eachLimit() 而不是 async.each() 來限制 request.get() 的最大數量,這樣你就不會一次用太多的 request.get() 刷新服務器。 在下面的示例中,我使用 5 作為並發處理的最大請求數,但您可以更改服務器 ecan 處理的值:
function getNewsTitles(targets, subs, callback) {
async.eachLimit(targets, 5, function (current, eachCb) {
request.get({
uri: current,
encoding: null
}, function(err, response, body) {
if (!err && response.statusCode == 200) {
var $ = cheerio.load(iconv.decode(body, 'EUC-KR'));
var subject = $('.articleSubject a');
for (var i = 0; i < subject.length; i++) {
subs.push(subject[i].attribs.title);
}
if (subs.length == (targets.length - 2) * 20 + 2) {
// when error or not, below log shows one time.
console.log('doubt here too');
}
}
eachCb(null); // must be called for every iteration of async.eachLimit()
});
}, function (err) {
callback(null); // all items have been processed, call this callback only once
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.