簡體   English   中英

Node.js 異步瀑布()回調已被調用

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM