关于nodejs回调执行顺序问题的一个例子,我无法理解

时间:2014-06-29 21:46:26

标签: javascript node.js asynchronous callback

我写了一个示例代码。

//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. '); 
}

然后,在运行节点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()需要更多时间来执行?

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

谢谢〜!

2 个答案:

答案 0 :(得分:2)

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

其他两个语句执行同步,这意味着它们将直接运行。因此,它们会在文件列表之前打印出来。

答案 1 :(得分:2)

异步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");
});

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