【问题标题】:a example about the issue of nodejs callback execution order that I can't understand一个我看不懂的nodejs回调执行顺序问题的例子
【发布时间】:2014-08-20 06:15:51
【问题描述】:

下面我写了一个示例代码。

//test.js
var fs = require('fs');
fs.readdir(__dirname+'/app/img/', function(err, files) {
    console.log(files);
});

someFunction(function(output){
    console.log(output);
});

console.log('This is the final console call');

function someFunction(callback) {
    callback(' I am some funciton. '); 
}

然后,运行“node test.js”后,我得到了以下结果。

$ node test2.js 
 I am some funciton. 
This is the final console call
[ 'photo1', 'photo2' ]

someFunction() 是我自己创建的,用于模拟 fs.readdir() 中的回调函数。 作为我最初的假设,结果应该是

[ 'photo1', 'photo2' ]
 I am some funciton. 
This is the final console call

This is the final console call
[ 'photo1', 'photo2' ]
 I am some funciton. 

但是现在 fs.readdir() 和 someFunction() 的日志分别出现在最终调用日志的前后。

嗯....我完全想不通。


因此,我的问题是:

为什么来自 fs.readdir() 的日志是最后一个日志?

是因为 fs.readdir() 需要更多时间来执行吗?

或者,我对这个问题缺乏一些重要的概念?

谢谢~!

【问题讨论】:

标签: javascript node.js asynchronous callback


【解决方案1】:

异步 ​​NodeJS 接口的全部意义在于,您可以继续运行您的程序,而无需等待 readdir 等长延迟函数返回结果。您调用 eraddir 告诉它开始处理,继续运行您的程序,当 readdir 完成时,它将安排调用您传递的回调函数。如果您同时调用多个异步函数,则无法保证哪个会先完成。

如果您希望所有这些 console.logs 函数按顺序执行,您需要嵌套回调

var fs = require('fs');

function someFunction(callback) {
    callback(' I am some funciton. '); 
}

fs.readdir(__dirname+'/app/img/', function(err, files) {
    console.log(files);
    someFunction(function(output){
        console.log(output);
        console.log('This is the final console call');
    });    
});

一种延迟稍微好一点的方法是一次执行所有调用,然后等到一切都完成后再打印结果。

// receives an array of computations to run in parallel
// calls a callback with an array with the results when all computations are done
// each computation is a function that takes a return callback as its first parameter.
function parallel(computations, callback){
    var results = [];
    var n = 0;

    computations.forEach(function(comp, i){
        comp(function(result){
            n++;
            results[i] = result;
            if(n === computations.length){
                callback(results);
            }
         });
    });
}

var fs = require('fs');

function someFunction(callback) {
    callback(' I am some funciton. '); 
}

parallel([
    function(cb){
        fs.readdir(__dirname+'/app/img/', function(err, files) {
            cb(files);
        });
    },
    function(cb){
        someFunction(function(output){
            cb(output);
        });
    },
], function(results){
    console.log(results[0]);
    console.log(results[1]);
    console.log("This is the final console call");
});

不过,我不建议手动编写这种并行同步。有许多异步编程库可以让这个过程更愉快,并提供更多功能。

【讨论】:

  • 感谢您的示例。看起来很清楚!是的,我知道 npm 中有“异步”。但我想在使用库解决问题之前完全弄清楚这个问题。这就是我来这里的原因,再次感谢!
  • 嗯,不知道哪一个对你来说更清楚。 this earlier revision 以低级但脆弱的方式执行操作,或者当前版本实现了与 async 中的并行化功能类似的版本
  • 哇,你好酷哈哈。对我来说,较早的是一个基本的 & 直接 解决方案。我的意思是,如果我需要自己写这个功能,那几乎是我能想象到的。但我知道必须有一些更聪明的解决方案,具有更好的结构和灵活性,然后,你只需给我看,还有一个清晰的代码。因此,我认为这两个对我来说都很清楚。但更重要的是,通过这两个版本,它可以让我从低到高一步一步地思考概念/解决方案。所以两者都很好,对我来说是必需的!
【解决方案2】:

fs.readdir 函数是异步执行的,而其他两个则不是。这意味着 fs.readdir 中的函数将在读取所有目录后执行(这可能需要一段时间)。

另外两个语句是同步执行的,这意味着它们将直接运行。因此它们被打印在文件列表之前。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-20
    • 2013-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2013-11-24
    相关资源
    最近更新 更多