Javascript nodeJS异步vs同步

Javascript nodeJS异步vs同步,javascript,node.js,express,Javascript,Node.js,Express,在nodeJS中,一般的做法和建议是使用async方法并回调到下一个函数 为了测试的目的,我设置了一个nodeJS,并编写了sync和async方法。无论使用async还是sync方法,这两种方法都有效,express都将响应所有请求,而不会出现任何可察觉的延迟 尽管我在项目中使用了async方法,但我读到的鼓励使用async方法的文章并没有深入解释原因。 Sync方法将避免出现错误 所以我很好奇,既然它们都能工作,为什么不使用sync方法呢?使用一种或另一种会影响响应时间/性能吗?嗯 你可以把

在nodeJS中,一般的做法和建议是使用async方法并回调到下一个函数

为了测试的目的,我设置了一个nodeJS,并编写了syncasync方法。无论使用async还是sync方法,这两种方法都有效,express都将响应所有请求,而不会出现任何可察觉的延迟

尽管我在项目中使用了async方法,但我读到的鼓励使用async方法的文章并没有深入解释原因。 Sync方法将避免出现错误

所以我很好奇,既然它们都能工作,为什么不使用sync方法呢?使用一种或另一种会影响响应时间/性能吗?

你可以把食物放进微波炉,同时洗个澡,当你洗完澡后,你可以(可能)把食物从微波炉里拿出来吃。如果食物还没有准备好,你可以做些别的事情,直到它准备好。这就是异步方式


或者,你可以把食物放在微波炉里,盯着微波炉直到它结束,吃你的食物,然后洗澡。这就是同步方式。

考虑到下面的代码:

server.get('/wait', function(request, response){

    var wait = true;
    while (wait) { // force synchronous delay of 10s
        setTimeout(function() {
            console.log('answering now');
            response.send('<pre>hello, i am 10s late</pre>');
            wait = false;
        }, 10000);
    }
});

server.get('/now', function(request, response){

    response.send('<pre>hello!</pre>');
});
server.get('/wait',函数(请求、响应){
var wait=true;
while(wait){//强制同步延迟10秒
setTimeout(函数(){
console.log('立即应答');
回复。发送(“你好,我迟到10秒”);
等待=错误;
}, 10000);
}
});
get('/now',函数(请求、响应){
回复。发送('hello!');
});

先呼叫,然后再呼叫

/now
立即得到回答。一个线程不相互干扰


先呼叫,然后再呼叫


第二个电话在第一个电话接听之前不会接听。一个线程不会相互干扰。

节点在单个线程上运行。如果您正在处理大量连接,那么肯定会有比CPU任务更多的IO任务。例如,DB调用。 在等待数据库查询结果时,您可以接收更多请求,或执行其他作业

当您需要执行CPU受限的任务时,问题就开始了:这项任务可能需要花费很多时间。您需要拆分任务,将其分成一小部分,然后将其余部分安排到稍后的时间,直到任务完成为止,或者您可以将其委托给另一个服务器/进程

如果您决定进行同步,则服务器在执行该任务时将不会再处理任何请求。是的,您将避免回调地狱,但代价是从开始到结束执行一项任务,不管它有多长。如果你试图处理大量的连接,这将是不好的

当出现故障时,一个很好的例子是for循环:

在“执行某些操作”时,服务器应用程序不会处理任何其他传入请求。当然,当你有更繁重的任务和大量的请求时,问题会更严重

在一个严肃的节点服务器中,您不需要同步循环,除非由于X动机,它的性能比异步解决方案好。因此,您可以与setTimeout、setImmediate、process.nextTick、Promises等异步。而且,您可能采用的第一种方法是继续传递样式,这意味着,在工作完成后传递要执行的回调,并且可能会碰到回调的地狱墙

那是你兑现承诺或发电机的时刻,或两者兼而有之:

通过这种方式,您将避免地狱般的回调,并获得更好的代码(主观)。另外,您可能还需要关注async/await:

您没有任何明显的优势,因为您是唯一提出请求的用户。例如,使用数千个连接进行测试


Abrazo。

这取决于您异步执行的操作。如果这是一项琐碎的任务,就不会花费太多时间。但是考虑一个web请求,无法保证服务器何时响应。它甚至可以让您保持等待(例如日志轮询)。异步调用会阻塞当前线程。我将这个express服务器设置为90%将JSON返回到ajax请求。存储在这些JSON中的数据是从本地硬盘检索的,有时是从第三方服务器检索的。即使您无法感知,访问HDD也需要相当长的时间,更不用说第三方服务器(网络)访问了。试着测量所花的时间,自己看看。也许一次读取不会成为问题,但如果您的服务被多个用户使用,那么每个人都必须等待其他请求完成。这与您的单个请求中的明显延迟无关。这是关于当服务器处理来自许多用户的许多请求时的阻塞。请注意,在微波炉打开时盯着微波炉可能会导致癌症。当在javascript中不必要地使用同步函数时,与此相同:D@noisypixy你的解释不是技术性的。没有提供任何代码来证明你的理论。@Azevedo,这不是技术性的,也不是可食用的建议。事实上,微波是最令人担忧的IDE之一,因为它的主要用途是制作食物。头脑中的裸节点是单线程的,通过使用事件驱动系统来模拟多线程。回调给出了异步行为的幻觉,但是节点没有运行在线程模型上。还要注意,使用异步方法的原因是因为您没有持有事件队列——考虑一个具有GUI运行的应用程序和一些长时间运行的底层代码,它们同步运行。如果您想等待这项工作完成,那么您正在阻塞事件队列,防止在该方法执行时发生任何其他事件,从用户体验的角度来看,这是非常糟糕的。您可能还想查看承诺,这样您就可以设置一个管道,说明代码应该如何执行,而无需执行
for (let x of ['some', 'huge', 'array']) {
  // Do something heavy here, until it's not finished, server won't do
  // anything more than this heavy task
}