Javascript Node.js异步任务是否同步处理?

Javascript Node.js异步任务是否同步处理?,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,考虑以下代码: var some_expensive_task = function(i) { setTimeout(function() { var a = 1; while (a < 100000000) { Math.sqrt(a); ++a; } console.log('finished set' + i); }, 0); }; for (var

考虑以下代码:

var some_expensive_task = function(i) {
    setTimeout(function() {
        var a = 1;

        while (a < 100000000) {
            Math.sqrt(a);

            ++a;
        }
        console.log('finished set' + i);
    }, 0);
};

for (var i = 0; i < 70; ++i) {
    console.log('start ' + i);
    some_expensive_task(i);
    console.log('end ' + i);
}
在整个执行过程中,只有两个进程。我假设其中一个是空闲事件循环,另一个是100%运行的工作进程

我的理解正确吗?当事件循环同步执行时,启动的异步任务(无论来自何处)都会按照调用顺序同步执行

更新


我仍然觉得我的问题表达得不够清楚。使用setTimeout是我能想到的唯一一种方法,它可以准确地安排一组异步函数运行。我想真正的问题是,如果我用setTimeout启动三个异步函数,仍然是零延迟,那么我启动的第二个函数是否保证在第一个函数完成后运行,第三个函数是否保证在第二个函数完成后启动?

是的。Javascript,包括NodeJS,是单线程的(除了少数例外)


当您使用
setTimeout(fn,0)
时,它会在清除当前调用堆栈后对要运行的函数进行排队。在您的示例中,这意味着
for
循环将在“昂贵的任务”运行之前完成。

Node.js是单线程的,并且在一个进程中运行,因为JavaScript是单线程的。因此您是正确的。

您的JS代码在Node.JS中的单个线程中运行。所有其他native Node.js API都是用C/C++编写的,它们要么是异步的,要么在单独的线程上运行。 有关更详细的说明,请参见

我的理解正确吗?当事件循环同步执行时,启动的异步任务(无论来自何处)都会按照调用顺序同步执行


是的,您是正确的。

您在问题中使用了不正确的术语,
是同步处理的Node.js异步任务
没有多大意义。测试用例并不是你想象的那样。首先明确一些术语:

同步函数保证按调用顺序运行/完成

异步函数可以按照其调用的顺序进行和完成

阻塞操作是指一旦启动就必须完成的操作,以使执行进一步进行。CPU密集型操作会阻塞,除非您在单独的辅助进程上运行它们。循环本质上是阻塞的。一旦开始,它们将在执行下一个函数之前完成所有迭代

setTimeout仅在当前时间后至少x毫秒调用传递的函数。调用它意味着一旦x ms pass,它就会在事件循环中对传递的函数进行排队。这只是延迟执行

因此,考虑到上述事实,以下是您的测试具有误导性的原因:

  • 首先,您的测试用例(CPU密集型函数)不是异步的,您将它包装在一个异步的setTimeout中。0的超时仅仅意味着它们将按照调用的相同顺序执行。所有回调函数都是同步的

  • 其次,日志中的start和end指示调用setTimeout的点。这将符合预期。超时为0时,完成也将正常进行。是的,如果保持它们的超时相等,则它们都将按照传递的相同顺序执行。这也是许多可能的情况之一,其结果类似于同步(如果超时的顺序是递增的呢?)。在这些情况下,你的要求可能是正确的,但并不总是正确的

  • 第三,如果您想要模拟异步性(足以看到控制台上的无序行为),那么最好松开while循环并使用随机超时(
    Math.random()*1000
    )。您将看到它们以任意方式完成。这将是异步执行(setTimeout而不是回调)


我认为您需要区分异步任务(等待0毫秒)和回调(cpu密集型同步循环)@Bergi,我想本例中的任务只是为了提供一种函数内延迟来说明执行的顺序。如果您想要多线程处理,您可能需要查看位于的
子进程
模块。
异步函数可以按照调用顺序进行和完成。
我不知道理解这句话。函数从入口点到出口点始终是同步的。他们可能会安排稍后调用的任务,但这并不意味着他们做了任何不符合顺序的事情。至少这不是一个正式的定义。异步函数是不存在形式化的。因此不存在同步函数。只有函数。再详细说明一下:这个函数是
var L=[];函数T(x){L.push(x);}
同步还是异步?@freakish:javascript中没有“异步函数”,没错。所有函数都同步运行,直到它们返回到调用方。但是,环境为我们提供了一些函数,这些函数接受回调函数,启动异步任务,并在完成回调后安排回调,然后立即返回
setTimeout
就是这样一个环境函数:它同步地立即返回一个计时器id,并在内部安排回调,以便将来以任何顺序调用。当然,该javascript函数的执行是同步运行的。@user568109:
setTimeout
始终是异步的,即使您超过了0毫秒的超时时间。在回调返回之前,它从不运行回调。也许正确的问题是:异步任务是否会阻止其他异步任务?
start 1
end 1
...
start 69
end 69
finished set1
...
finished set69