简体   繁体   English

Node.js模块中的异步功能

[英]Async functions in Node.js module

I'm kind of new to JavaScript/Node.js so bear with me. 我是JavaScript / Node.js的新手,请耐心等待。 Also my english may not be that good. 我的英语也可能不太好。

I'm trying to write a Node.js module module.js with functions that do some long-running work. 我正在尝试编写一个具有一些长时间运行功能的Node.js模块module.js Kind of like this: 有点像这样:

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);
    })
};

Now, I also have a main.js where I invoke these functions: 现在,我还有一个main.js在其中调用以下函数:

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

var output1 = module.myFunction1();

var output2 = module.myFunction2();

My first problem is that my functions return undefined . 我的第一个问题是我的函数返回undefined I understand that this is because the exec function runs asynchronously and therefore the function returns before exec has finished. 我了解这是因为exec函数异步运行,因此该函数在exec完成之前返回。 This is basically what I want but how can I tell my function that it should only callback when exec has finished? 这基本上是我想要的,但是我如何告诉我的函数只应在exec完成后才进行回调?

I also don't want the functions to block node.js when I invoke them in my main.js. 当我在main.js中调用它们时,我也不希望这些函数阻塞node.js。 So basically, my output of the above code would be... 所以基本上,我上面代码的输出将是...

Output myFunction2: Output2
Output myFunction1: Output1

...because myFunction2() finishes faster than myFunction1(). ...因为myFunction2()的完成速度比myFunction1()快。

I tried many, many solutions I found online but nothing seems to work properly. 我尝试了许多在网上找到的解决方案,但似乎没有任何正常工作。

Thank you very much in advance! 提前非常感谢您!

--- EDIT --- -编辑-

Ok, I'm having a somewhat correct solution. 好的,我有一个正确的解决方案。 Right now my code looks like this: 现在,我的代码如下所示:

module.js 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;
    }
}

My main.js lloks like this now: 我的main.js现在会像这样:

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)
});

And I get the expected output: 我得到了预期的输出:

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

My Problem now is, that myFunction1() always logs before myFunction2(), even if myFunction2() finished first. 我的问题现在是,即使myFunction2()首先完成,myFunction1()总是在myFunction2()之前记录。 Did I understood something wrong about Promises? 我是否了解有关Promises的问题? Shouldn't myFunction2() return immediately after it finished? myFunction2()完成后不应该立即返回吗?

Your functions take callbacks. 您的函数接受回调。 Those parameters are functions which are called on completion, which makes it easy to do 这些参数是在完成时调用的函数,因此操作起来很容易

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);
});

Using a callback, in your case, is the simplest solution but you should be aware that there are other patterns to deal with asynchronous executions. 在您的情况下,使用回调是最简单的解决方案,但是您应该意识到还有其他模式可以处理异步执行。 Here's a good overview . 这是一个很好的概述 For example, a popular solution, especially interesting when you have to chain asychronous continuations, is to use promises , which allow 例如,一种流行的解决方案是使用promises ,这在您必须链接异步延续时特别有趣,它可以允许

var exec = require('child_process').exec;
module.exports.myFunction1 = function() {
    return new Promise(function(resolve, fail){
        // this function runs for like 3 seconds
        exec('long running shell command' ,function(err,stdout,stderr) {
            if (err) fail(err);
            else resolve(stdout, stderr);
        });
    });
};

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

At first, I would suggest you to handle errors ( err , stderr ) in your modules. 首先,我建议您处理模块中的错误( errstderr )。 As you can see, your functions takes one argument which is callback. 如您所见,您的函数采用一个参数,即回调。 If your asynchronous function runs, the callback function is called. 如果您的异步函数运行,则调用回调函数。 So you can use it like this: 因此,您可以像这样使用它:

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

exec function also takes callback function (with first argument error err - error first callbacks). exec函数还接受回调函数(第一个参数错误err错误的第一个回调)。 There are other options how to handle flow control of asynchronous code (eg library async ). 还有其他方法可以处理异步代码的流控制(例如,库async )。 You can also learn about Promises which is today's alternative to error first callbacks. 您还可以了解Promises ,它是今天的错误优先回调的替代方法。

Callback functions don't return values directly... what you need is to setup what will happen when value will get read. 回调函数不会直接返回值...您需要的是设置读取值时将发生的情况。 Something like this: 像这样:

my_function(what_will_happen_when_my_function_will_get_finished());

exectly: exectly:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM