Node.js模块中的异步函数

时间:2016-01-10 11:13:14

标签: javascript node.js

我是JavaScript / Node.js的新手,所以请耐心等待。我的英语也可能不那么好。

我正在尝试编写Node.js模块 module.js ,其中包含执行长期运行工作的函数。有点像这样:

var exec = require('child_process').exec;

module.exports.myFunction1 = function(callback) {
    // this function runs for like 3 seconds
    exec('long running shell command' ,function(err,stdout,stderr) {
        callback(stdout);
    })
};

module.exports.myFunction2 = function(callback) {
    // this function runs for like 1 second
    exec('long running shell command' ,function(err,stdout,stderr) {
        callback(stdout);
    })
};

现在,我还有一个 main.js ,我调用这些函数:

var module = require('./module.js');

var output1 = module.myFunction1();

var output2 = module.myFunction2();

我的第一个问题是我的函数返回 undefined 。我知道这是因为exec函数异步运行,因此函数在exec完成之前返回。这基本上就是我想要的但是我怎么能告诉我的函数它只应该在exec完成时回调?

当我在main.js中调用它们时,我也不希望函数阻塞node.js.所以基本上,上面代码的输出将是......

Output myFunction2: Output2
Output myFunction1: Output1

...因为myFunction2()的结束速度比myFunction1()快。

我在网上找到了很多很多解决方案,但似乎没有什么工作正常。

非常感谢你!

---编辑---

好的,我的解决方案有点正确。现在我的代码看起来像这样:

module.js

var Q = require('q');
require('shelljs/global')

module.exports = {
    myFunction1: function () {
        var deferred = Q.defer();

        var result = exec('long running command', {silent:true}).output.toString();

        if (ok) {
            deferred.resolve(result);
        }
        else {
            deferred.reject('Error');
        }

        return deferred.promise;
    },

    myFunction2: function () {
        var deferred = Q.defer();

        var result = exec('long running command', {silent:true}).output.toString();

        if (ok) {
            deferred.resolve(result);
        }
        else {
            deferred.reject('Error');
        }

        return deferred.promise;
    }
}

我的 main.js lloks现在这样:

var module = require('./module');

module.myFunction1()
    .then(function (result) {
        console.log('Result 1: ' + result);
    })
    .fail(function (error) {
        console.log(error)
});

module.myFunction2()
    .then(function (result) {
        console.log('Result 2: ' + result);
    })
    .fail(function (error) {
        console.log(error)
});

我得到了预期的输出:

Result 1: Output that myFunction1() generated
Result 2: Output that myFunction2() generated

我现在的问题是,myFunction1()总是在myFunction2()之前记录,即使myFunction2()先完成。我对Promises有什么不妥吗?完成后myFunction2()不应该立即返回吗?

3 个答案:

答案 0 :(得分:1)

您的功能需要回调。这些参数是在完成时调用的函数,这使得它很容易实现

struct task_struct *task; 
struct list_head *list;
list_for_each(list, &current->children) { 
task = list_entry(list, struct task_struct, sibling); /* task now points to one of current’s children */ 
}

在您的情况下,使用回调是最简单的解决方案,但您应该知道还有其他模式可以处理异步执行。这是a good overview。例如,一个流行的解决方案,特别是当你必须链接异步延续时很有意思的是使用 promises ,这允许

var exec = require('child_process').exec;
module.exports.myFunction1 = function(callback) {
    // this function runs for like 3 seconds
    exec('long running shell command' ,function(err,stdout,stderr) {
        callback(stdout);
    })
};

module.myFunction1(function(stdout){
      console.log("Output myFunction1: " + stdout);
});

答案 1 :(得分:0)

首先,我建议您在模块中处理错误(errstderr)。如您所见,您的函数采用一个参数即回调。如果您的异步函数运行,则调用回调函数。所以你可以像这样使用它:

module.myFunction1(function(stdout) {
    console.log("Output myFunction1: " + stdout);
    module.myFunction2(function(stdout2) {
        console.log("Output myFunction2: " + stdout2);
    });
});

exec函数也接受回调函数(第一个参数错误err - 错误第一个回调)。如何处理异步代码的流控制还有其他选择(例如库async)。您还可以了解Promises,它是今天错误优先回调的替代方法。

答案 2 :(得分:0)

回调函数不会直接返回值...您需要的是设置读取值时会发生什么。像这样:

my_function(what_will_happen_when_my_function_will_get_finished());

exectly:

myFunction1(function(data){console.log('hello! I've finished, and received: '+data);});