5

拜托,只是为了清除我脑海中的某些东西...

我习惯于在库中使用异步函数进行编写,但如何编写自己的函数呢?

为了说明我的问题,我制作了一个名为“MadMathz”的模块

我知道以下是异步函数的示例用法:

//load module
var mM = require('./MadMathz');

//perform a function
mM.async_function_addthree(12, function(result) {
  console.log(result)
});

//do something straight afterwards
console.log('Logging this straight after instead of waiting for computation');

我知道该函数的第二个参数是回调,但是如何定义诸如“async_function_addthree”之类的函数?假设出于此示例的目的, async_function_addthree 只是将 3 添加到第一个参数。

我只是把自己弄糊涂了,试图写出我认为可能是的东西。我完全走错了吗?我觉得我已经接近使用 node.js 了,但这需要清理。

如果可能的话,请解释而不是将我链接到某个地方。我相信其他人将从这个问题中受益。

4

4 回答 4

17

实际上,在没有任何进一步描述或要求的情况下创建“异步”函数听起来有点奇怪。通常,使用是为了避免长时间的阻塞。因此,如果我们有一个触发数据库查询的函数,并且我们想在完成后调用另一个函数,则应该在作业完成调用该函数,并且原始函数会立即将控制流返回给Node (ECMAscript) .

所以如果我们有一个像

function someJob( callback ) {
    // heavy work
    callback();
}

现在,这段代码仍然非常同步地运行。为了使其处于异步状态,我们可以调用节点的process.nextTick方法

function someJob( callback ) {
    // heavy work
    process.nextTick( callback );
}

现在发生的事情是,Node 将在稍后通过其事件循环运行时执行该回调方法(它也这样做有点智能)。EventhonextTick声称比它更有效setTimeout,它几乎是相同的交易(从 ECMAscript 编码器的角度来看)。所以在浏览器中我们可以像

function someJob( callback ) {
    // heavy work
    setTimeout( callback, 0 );
}

如果说上面的示例方法根本没有多大意义,那是正确的,因为异步状态发生繁重的工作之后。嗯,没错。事实上,你需要把重的部分分解成更小的部分,并利用相同的想法来.nextTick()提高效率。

这也是我一开始困惑的原因,其实每一个任务都已经为你提供了回调的可能性。

于 2012-10-11T09:13:45.160 回答
1

这不是 node.js 模块代码,但我希望你能明白。

函数是 JavaScript 中的第一类对象。这就是为什么您可以将它们分配给变量并将它们像任何值一样传递给其他函数。一旦你有一个函数的引用,你只需()在函数引用后面加上它来调用它。

例子:

function async_function_addthree(a, callback) {
    callback(a + 3);
}

这将添加3到第一个参数,然后调用第二个参数将结果传递给它。请记住,您可以随意命名参数。重要的是第二个参数将包含一个您可以调用的函数。

但请注意:接受回调的函数不会自动异步。在这个例子中,代码仍然按照定义的顺序执行,即首先async_function_addthree,然后是回调,然后是调用之后的所有内容async_function_addthree,例如console.log.

您可以添加一个setTimeout并延迟调用回调:

function async_function_addthree(a, callback) {
    setTimeout(function() {
        callback(a + 3);
    }, 1000);
}

这将在一秒钟后调用回调。Node.js 甚至内置了更好的方法,请参阅jAndy 的回答

但即使您的代码不是异步的,使用回调也是一个明智的设计选择,因为它允许您轻松更改函数的行为并在以后使其异步而不破坏现有代码。

于 2012-10-11T09:08:11.353 回答
0

当您将一些工作委派给外部进程(或者可能是 Node 的 C 层中的一些工作)时,NodeJS 进程中的异步就会发生,例如数据库查询、文件系统操作。

通常在普通的 JavaScript 函数中没有异步性(Node.js 是单线程的),没有多少有效的案例。但是,如果它真的很重,并且您真的想这样做,您可以将您的工作委托给其他进程(参见 child_process.fork)或在 setTimeout 的帮助下拆分操作(让进程喘息以处理其他请求),然后确实应该将其配置为异步功能。

于 2012-10-12T08:25:26.040 回答
0

我在自己寻找答案时遇到了这个问题。

基本上,要在节点中编写一个异步函数,你给它的参数之一应该是一个函数;您稍后将在异步函数中调用该函数。

然后,当人们调用您的函数时,他们将能够定义该函数。

这是我以同步方式编写但不起作用的代码示例,以及我如何将其重写为异步并实际工作。


以下代码不起作用:

//synchronous function that doesn't work
var google_request  = function(animal_name, sessionid){
    var options = {
        url: 'http://google.com',
        method: 'POST',
        json: {
            "animal": animal_name,
            "sessionid": sessionid
        }
    };

    request(options, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            return body;
        }
    });
};

//use your function
var body = google_request("ant", "session1")
console.log(body); //this will return undefined

以下代码确实有效:

//asynchronous function
var google_request  = function(animal_name, sessionid, callback_function){
    var options = {
        url: 'http://google.com',
        method: 'POST',
        json: {
            "animal": animal_name,
            "sessionid": sessionid
        }
    };

    request(options, function (error, response, body) {
        if (!error && response.statusCode == 200) {
            callback_function(body);
        }
    });
};

//use your function
google_request("ant", "session1", function(body){
    console.log(body); 
)};

这可能不是最简单的例子,但我对这个函数所做的更改非常简单;我向函数传递了第三个参数,称为“callback_function”,而不是返回“body”,而是在 body 上调用了 callback_function。然后在下面我以通常的“节点”方式使用我的函数,而不是同步方式。

您可能还会发现此线程提供了丰富的信息:如何从异步调用返回响应?

于 2014-06-09T15:15:15.127 回答