异步调用同步函数

时间:2013-07-14 14:05:48

标签: javascript node.js asynchronous

假设我有一个同步功能,例如:

var sum = function(x,y){
  return x+y
}

我想以异步方式调用此函数。怎么可能?以下函数是否被视为异步函数?如果这是一个异步函数,那么第二个函数的日志应该在第一个之前记录?我知道这是一个非常简单的例子,可能不是异步函数的理想情况。但我只想明确这一点。

function(a, b, c, d, e, f, function(){
  console.log(result);
})
{
   result = sum(a, b);
   result = sum(result, c);
   result = sum(result, d);
   result = sum(result, e);
   result = sum(result, f);
   return
)};


function(a, b, function(){
  console.log(result);
})
{
   result = sum(a, b);
   return
)};

请帮帮我。如果这不正确,那么请帮助我如何写出来?

4 个答案:

答案 0 :(得分:3)

来自你对昆汀答案的评论

  

如何创建一个在其中有一些操作的函数,这是一个正常的同步函数,但整个流程不等待这个函数完成而是转移到下一个函数。

JavaScript,这种语言,没有这方面的功能。因此,您要查看其运行的环境,以查看环境是否具有该功能。

NodeJS。事实上,它有几个:setTimeout(有点像浏览器给你的),setImmediateprocess.nextTick。对于您的用例,setImmediate可能是最佳选择,但see this question and its answers for more on thatsetImmediate看起来像这样:

setImmediate(functionToCall);

(这是全球性的,你没有require任何东西。)

这正是你的标题所要求的:对同步函数的异步调用。


根据您的评论:

  

我只需要创建一个异步函数,我称之为普通的同步函数。当我的意思是异步函数时,我的意思是当我调用这个函数时它不会阻塞流程并且流程转到下一个函数,并且该函数可以在完成后执行某些操作(如日志记录)

这个问题并不完全相同。 : - )

首先,没有异步函数(在JavaScript中)。在JavaScript中调用函数时,该函数将同步执行。这意味着你有两个选择:

  1. 调用代码可以使用setImmediate告诉Node异步调用函数,或者

  2. 该函数可以为自己完成,可能使用嵌套函数。

  3. 这是#1:

    function foo() {
        console.log("A");
        setImmediate(bar);
        console.log("B");
    }
    function bar() {
        console.log("C");
    }
    foo();
    

    输出:

    A
    B
    C

    这是#2:

    function foo() {
        console.log("A");
        bar("C");
        console.log("B");
    }
    function bar(arg) {
    
        setImmediate(run);
    
        function run() {
            console.log(arg);
        }
    }
    foo();
    

    ...也输出

    A
    B
    C

    注意“C”如何作为参数传递给barbar除了将回调安排到其嵌套函数run之外什么都不做。 run使用参数。

答案 1 :(得分:0)

  

这怎么可能?

不是。它所做的一切都是同步操作。

在处理本质上异步的事物时,您使用异步代码。这在JS中是有限的,几乎完全是为了事件处理。

  

下面的函数是否被视为异步函数?

没有。它有一个回调,但它所做的一切都是同步的。

答案 2 :(得分:0)

我不完全确定我理解你需要什么,但我相信你正在寻找的是创建并发函数调用,这意味着你可能需要运行一个潜在的计算密集的代码,并且您不希望它在此计算运行时阻止执行其他代码。 Node.js 通常用于单线程进程,这意味着在给定时间只能运行一段代码,但仍有一些方法可以执行此操作。

一种方法,如@ T.J中所述。 Crowder的回答是,用 process.nextTick 对你的函数调用进行排队,这样它就会在事件循环的下一个循环中运行。这可以帮助将密集计算分解为迭代,并且每个迭代将排队以在最后一个之后的下一个事件循环周期上运行。在某些情况下,这可能有所帮助,但并非总是可以将计算分解为彼此异步运行的迭代。如果您正在寻找有关Javascript如何异步运行的更详细说明,我建议您阅读this book

至少有两种方法(我知道)可以通过 Node.js - 工作人员/线程和子进程实现某种并发。 简而言之子进程只是由主应用程序运行的另一个Node.js进程。如果您想这样做,可以使用 Node.js 的native * child_process *模块来运行和管理子进程。查看official docs了解更多信息。

第三种方法是以与Web Workers在浏览器中使用方式非常相似的方式使用Workers。 Worker是一段代码,它在与主应用程序不同的OS线程中运行。对我而言,这似乎是实现并发的最简单方法,尽管有些人认为它不是最强大的方法,并且创建子进程更好。

有关工人如何在MDN上运作的非常好的解释。要在 Node.js 中使用Workers,您需要一个外部模块,例如webworker-threads

以下是从您的示例创建的代码示例,其中包含其文档中的代码段:

var Worker = require('webworker-threads').Worker;

var worker = new Worker(function(){
    onmessage = function(event) {
        result = sum(event.data.a, event.data.b);
        result = sum(result, event.data.c);
        result = sum(result, event.data.d);
        result = sum(result, event.data.e);
        result = sum(result, event.data.f);
        postMessage(result);
        self.close();
    };
});
worker.onmessage = function(event) {
    console.log("The result is: " + event.data);
};
worker.postMessage({a: 1, b: 2, c: 3, d: 4, e: 5, f: 6});

// Do some other stuff that will happen while your Worker runs...

尽管如此,大多数人都会尽量避免在 Node.js 中运行并发代码。 Javascript的异步性质使得编写简单而简洁的后端代码变得容易,并且通常您希望通过不尝试将并发引入应用程序来保持这种方式,除非绝对必要。

答案 3 :(得分:-2)

在Javascript中(暂时离开节点)应该通过setTimeout()调用异步函数。 SetTimeout不会在等待时阻止脚本执行:

function someThingThatTakesAWhile() { 
    for (var i = 0; i < someVeryLargeNumber; i++) {
        //...
    };
}
setTimeout(function () {
    someThingThatTakesAWhile();
}, 0);

(尚未测试过,请原谅错别字,&amp; c)

但如果您想在节点中执行此操作,我认为这不是您真正想要的。