Async: 使用 Async 和 Node 6.2.2 出现新错误“回调已调用”

创建于 2016-06-27  ·  12评论  ·  资料来源: caolan/async

您使用的是什么版本的异步?

3.9.5

问题发生在哪个环境(节点版本/浏览器版本)

节点 6.2.2 和 5.0.71.52

你做了什么?

这个应用程序

var fs = require('fs'),
    async = require('async'),
    _dir = './data/';

var writeStream = fs.createWriteStream('./log.txt',
      {'flags' : 'a',
       'encoding' : 'utf8',
       'mode' : 0666});

async.waterfall([
   function readDir(callback) {
      fs.readdir(_dir, function(err, files) {
         callback(err,files);
      });
   },
   function loopFiles(files, callback) {
      files.forEach(function (name) {
         callback (null, name);
      });
   },

   function checkFile(file, callback) {
      fs.stat(_dir + file, function(err, stats) {
         callback(err, stats, file);
      });
   },
   function readData(stats, file, callback) {
      if (stats.isFile())
         fs.readFile(_dir + file, 'utf8', function(err, data){
           callback(err,file,data);
       });
   },
   function modify(file, text, callback) {
      var adjdata=text.replace(/somecompany\.com/g,'burningbird.net');
      callback(null, file, adjdata);
   },
   function writeData(file, text, callback) {
       fs.writeFile(_dir + file, text, function(err) {
          callback(err,file);
       });
   },

   function logChange(file, callback) {
       writeStream.write('changed ' + file + '\n', 'utf8',
                       function(err) {
          callback(err);
      });
   }
], function (err) {
         if (err) {
            console.log(err.message);
         } else {
            console.log('modified files');
         }
});

你期望会发生什么?

我不会出错

实际结果如何?

我越来越

/home/examples/public_html/learnnode2-examples/chap3/node_modules/async/dist/async.js:837
if (fn === null) throw new Error("回调已被调用。");
^

错误:回调已被调用。

以下代码段中的回调函数

函数循环文件(文件,回调){
files.forEach(函数(名称){
回调(空,名称);
});
},

在第二次运行时丢失。

我已经通过多个版本的 Node.js 成功运行了这段代码。 我相信我在 Node 6 首次发布时确实对此进行了测试。

在第二次迭代中,该函数不为空,但 Async 代码中发生的某些事情导致了此错误。

question

所有12条评论

因为你在这里多次调用回调:

function loopFiles(files, callback) {
    files.forEach(function(name) {
        callback(null, name);
    });
},

对于这种情况,请使用 async.forEach。

有趣的。 我在使用以前版本的 Node 时没有遇到任何问题,事实上,我只是在我的 Windows 机器上的 Node 6.0.0 中成功运行了它。

因此,在 6.0.0 和 6.2.2 之间发生了一些变化,导致 Async 因使用内置 forEach 而中断。

仅供参考, async.forEach 不起作用。 它不会崩溃,但它不起作用。

   function loopFiles(files, callback) {
      async.forEach(files, function (name, callback) {
         callback (null, name);
      });
   },

坦率地说,我不确定是 forEach 导致了问题。 如果我使用不正确,请告诉我。

好吧,我放弃了。

我将我的 Windows 机器更新到 6.2.2,此代码有效。 但它在我的 Linux 机器上不起作用。 两者都建立在相同的 V8 引擎上。 两者都使用相同版本的 Async。 两者都有相同的示例文件目录。

在 Linux 中,会抛出错误。 在 Windows 中,不是。

@shelleyp对于多个文件,您的瀑布结构不正确。 我想你想把它分成两个瀑布,或者让每一步都期待一个数组。

您的async.forEach更改不起作用的原因是因为您没有调用loopFiles回调。 无论如何,该函数不会执行您想要的操作,如果您只想处理 firstFile 将 loopFiles 更改为(files, callback) => callback(null, files[0])否则您将需要checkFiles , readDatamodify期望数组(或创建第二个瀑布)

我不会修复你所有的代码,但这就是我如何改变你的checkFiles函数

async.waterfall([
   function readDir(callback) {
      fs.readdir(_dir, callback);
   },

   function checkFile(files, callback) {
      async.map(files, (file, cb) => {
         fs.stat(_dir + file, function(err, stats) {
            cb(err, {stat: stats, file: file});
         });
      }, (err, stats) => {
         callback(err, stats);
      });
   },

....

没关系。

只知道这在 6.2.2 之前一直有效,所以任何导致我的代码不起作用的东西都可能导致其他人的代码不起作用。

奇怪的是,应该使该代码工作的唯一事情是 readdir 列出
一个文件(它也被破坏为 0 个文件)。

你介意在两个版本的 nod 中仔细检查 readdir 的输出吗
2016 年 6 月 27 日下午 5:55,“Shelley Powers”通知@github.com写道:

没关系。

只知道这在 6.2.2 之前一直有效,所以无论导致我的代码不
工作可能会导致其他人的代码无法工作。


您收到此消息是因为您修改了打开/关闭状态。
直接回复本邮件,在GitHub上查看
https://github.com/caolan/async/issues/1199#issuecomment -228887866,或者静音
线程
https://github.com/notifications/unsubscribe/ADUIEAfvkwCmdjmkIZIjipFGYgPQ6SzYks5qQEbpgaJpZM4I_Nsg
.

此代码始终适用于多个文件。 好吧,直到 Linux 上的 6.2.2。

但只是在 Windows 上检查过。 是的,使用了四个文件。

readdir 的输出是 [ 'data1.txt', 'data2.txt', 'data3.txt', 'data4.txt' ]

loopFiles 的输入是相同的。

在那个时间点,对于 forEach,每个回调都会获得一个单独的文件名。

如果我曾经遇到过阵列的砖墙,我就不会使用这种方法。 但它总是奏效。

没什么大不了的,我可以随时更新代码以删除数组处理。 真正的问题是它在一种环境中有效,但在另一种环境中无效。 然而,Node、V8 和 Async 是相同的版本。

我只是在节点 6.0.0 和 6.2.2 的 Ubuntu 16.04 中运行了稍微修改的代码。 在这两种情况下,我都得到了相同的输出:

  • data1.txt,第一项的回调(data1.txt)
  • 错误:回调已被调用

修改后的脚本:

var fs = require('fs'),
    async = require('async'),
    _dir = './data/';

async.waterfall([
   function readDir(callback) {
      fs.readdir(_dir, callback);
   },
   function loopFiles(files, callback) {
      files.forEach(function (name) {
         callback (null, name);
      });
   },
   console.log.bind(console)
], console.error)
$ ls data
> data1.txt  data2.txt

但是你没有在 Windows 中尝试过。

当然,我关闭它不是一个异步问题。

2016 年 6 月 27 日星期一晚上 8:20,Shelley Powers [email protected]
写道:

但是你没有在 Windows 中尝试过。


您收到此消息是因为您修改了打开/关闭状态。
直接回复本邮件,在GitHub上查看
https://github.com/caolan/async/issues/1199#issuecomment -228914233,或者静音
线程
https://github.com/notifications/unsubscribe/ADUIEDNwRmcEjcAnVmSCHBBIHvdM6DL3ks5qQGiwgaJpZM4I_Nsg
.

此页面是否有帮助?
0 / 5 - 0 等级