【问题标题】:async.series and async.each not working as expectedasync.series 和 async.each 没有按预期工作
【发布时间】:2014-05-24 18:38:47
【问题描述】:

我正在尝试使用 nodeJS 构建一个网络爬虫,它在网站的 HTML 中搜索图像,缓存图像源 URL,然后搜索最大尺寸的。

我遇到的问题是 deliverLargestImage() 在循环通过图像源 URL 数组以获取其文件大小之前触发。我正在尝试同时使用 async.seriesasync.each 来正常工作。

如何强制deliverLargestImage() 等到getFileSizes() 内部的async.each 完成?

JS

var async, request, cheerio, gm;
async = require('async');
request = require('request');
cheerio = require('cheerio');
gm = require('gm').subClass({ imageMagick: true });

function imageScraper () {
  var imgSources, largestImage;
  imgSources = [];
  largestImage = {
    url: '',
    size: 0
  };

  async.series([
    function getImageUrls (callback) {
      request('http://www.example.com/', function (error, response, html) {
        if (!error && response.statusCode === 200) {
          var $ = cheerio.load(html);
          $('img').each(function (i, elem) {
            if ( $(this).attr('src').indexOf('http://') > -1 ) {
              var src = $(this).attr('src');
              imgSources.push(src);
            }
          });
        }
        callback();
      });
    },
    function getFileSizes (callback) {
      async.each(imgSources, function (img, _callback) {
        gm(img).filesize(function (err, value) {
          checkSize(img, value);
          _callback();
        });
      });
      callback();
    },
    function deliverLargestImage (callback) {
      callback();
      return largestImage;
    }
  ]);

  function checkSize (imgUrl, value) {
    var r, raw;
    if (value !== undefined) {
      r = /\d+/;
      raw = value.match(r)[0];
      if (raw >= largestImage.size) {
        largestImage.url = imgUrl;
        largestImage.size = raw;
      }
    }
  }
}

imageScraper();

【问题讨论】:

  • getFileSizes() 不会等待内部async.each 完成,而是立即触发callback()...

标签: javascript node.js asynchronous node-async


【解决方案1】:

尝试在此处移动callback()

function getFileSizes (callback) {
  async.each(imgSources, function (img, _callback) {
    gm(img).filesize(function (err, value) {
      checkSize(img, value);
      _callback();
    });
  }, function(err){ callback(err); }); /* <-- put here */
  /* callback(); <-- wrong here */
},

each 接受一个回调作为 third parameter,当每个元素的内部循环完成时执行:

参数

  • arr - 要迭代的数组。
  • iterator(item, callback) - 应用于arr 中每个项目的函数。 迭代器传递了一个callback(err),一旦它必须调用它 完全的。如果没有发生错误,callback 应该在没有错误的情况下运行 参数或显式 null 参数。
  • callback(err) - 当所有 iterator 函数时调用的回调 已完成,或发生错误。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 2016-08-13
    • 2013-07-07
    • 2012-12-05
    • 2017-05-22
    • 2019-07-28
    相关资源
    最近更新 更多