同步和异步编程有什么区别(在 node.js 中)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16336367/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 14:24:05  来源:igfitidea点击:

What is the difference between synchronous and asynchronous programming (in node.js)

javascriptnode.jsasynchronoussynchronous

提问by Azeirah

I've been reading nodebeginnerAnd I came across the following two pieces of code.

我一直在阅读nodebeginner并且遇到了以下两段代码。

The first one:

第一个:

    var result = database.query("SELECT * FROM hugetable");
    console.log("Hello World");

The second one:

第二个:

    database.query("SELECT * FROM hugetable", function(rows) {
       var result = rows;
    });
    console.log("Hello World");

I get what they're supposed to do, they query the database to retrieve the answer to the query. And then console.log('Hello world').

我得到了他们应该做的事情,他们查询数据库以检索查询的答案。然后console.log('Hello world')

The first one is supposedly synchronous code. And the second one is asynchronous code.

第一个应该是同步代码。第二个是异步代码。

The difference between the two pieces is very vague to me. What would the output be?

这两件作品之间的区别对我来说非常模糊。输出会是什么?

Googling on asynchronous programming didn't help me either.

谷歌异步编程也没有帮助我。

回答by Salvatorelab

The difference is that in the first example, the program will block in the first line. The next line (console.log) will have to wait.

不同的是,在第一个例子中,程序会在第一行阻塞。下一行 ( console.log) 将不得不等待。

In the second example, the console.logwill be executed WHILE the query is being processed. That is, the query will be processed in the background, while your program is doing other things, and once the query data is ready, you will do whatever you want with it.

第二个示例中console.log将在处理查询时执行。也就是说,查询将在后台处理,而您的程序正在做其他事情,一旦查询数据准备就绪,您将随心所欲地使用它。

So, in a nutshell: The first example will block, while the second won't.

所以,简而言之:第一个例子会阻塞,而第二个不会。

The output of the following two examples:

以下两个示例的输出:

// Example 1 - Synchronous (blocks)
var result = database.query("SELECT * FROM hugetable");
console.log("Query finished");
console.log("Next line");


// Example 2 - Asynchronous (doesn't block) 
database.query("SELECT * FROM hugetable", function(result) {
    console.log("Query finished");
});
console.log("Next line");

Would be:

将是:

  1. Query finished
    Next line
  2. Next line
    Query finished
  1. Query finished
    Next line
  2. Next line
    Query finished

Note
While Node itself is single threaded, there are some task that can run in parallel. For example, File System operations occur in a different process.

注意
虽然 Node 本身是单线程的,但有一些任务可以并行运行。例如,文件系统操作发生在不同的进程中。

That's why Node can do async operations: one thread is doing file system operations, while the main Node thread keeps executing your javascript code. In an event-driven server like Node, the file system thread notifies the main Node thread of certain events such as completion, failure, or progress, along with any data associated with that event (such as the result of a database query or an error message) and the main Node thread decides what to do with that data.

这就是 Node 可以执行异步操作的原因:一个线程正在执行文件系统操作,而主 Node 线程继续执行您的 javascript 代码。在像 Node 这样的事件驱动服务器中,文件系统线程会通知主 Node 线程某些事件,例如完成、失败或进度,以及与该事件相关的任何数据(例如数据库查询的结果或错误消息),主节点线程决定如何处理该数据。

You can read more about this here: How the single threaded non blocking IO model works in Node.js

您可以在此处阅读更多相关信息:单线程非阻塞 IO 模型如何在 Node.js 中工作

回答by Santosh Panda

The difference between these two approaches is as follows:

这两种方法的区别如下:

Synchronous way:It waits for each operation to complete, after that only it executes the next operation. For your query: The console.log()command will not be executed until & unless the query has finished executing to get all the result from Database.

同步方式:等待每个操作完成,然后才执行下一个操作。对于您的查询:console.log()除非查询已完成执行以从数据库中获取所有结果,否则该命令将不会执行,直到 &。

Asynchronous way:It never waits for each operation to complete, rather it executes all operations in the first GO only. The result of each operation will be handled once the result is available. For your query: The console.log()command will be executed soon after the Database.Query()method. While the Database query runs in the background and loads the result once it is finished retrieving the data.

异步方式:它从不等待每个操作完成,而是只在第一个 GO 中执行所有操作。一旦结果可用,将处理每个操作的结果。对于您的查询:该console.log()命令将在该Database.Query()方法之后立即执行。数据库查询在后台运行并在完成检索数据后加载结果。

Use cases

用例

  1. If your operations are not doing very heavy lifting like querying huge data from DB then go ahead with Synchronous way otherwise Asynchronous way.

  2. In Asynchronous way you can show some Progress indicator to the user while in background you can continue with your heavy weight works. This is an ideal scenario for GUI apps.

  1. 如果您的操作没有像从数据库查询大量数据那样进行繁重的工作,那么请继续使用同步方式,否则使用异步方式。

  2. 在异步方式中,您可以向用户显示一些进度指示器,而在后台您可以继续进行繁重的工作。这是 GUI 应用程序的理想方案。

回答by Martijn

This would become a bit more clear if you add a line to both examples:

如果您在两个示例中添加一行,这将变得更加清晰:

var result = database.query("SELECT * FROM hugetable");
console.log(result.length);
console.log("Hello World");

The second one:

第二个:

database.query("SELECT * FROM hugetable", function(rows) {
   var result = rows;
   console.log(result.length);
});
console.log("Hello World");

Try running these, and you'll notice that the first (synchronous) example, the result.length will be printed out BEFORE the 'Hello World' line. In the second (the asynchronous) example, the result.length will (most likely) be printed AFTER the "Hello World" line.

尝试运行这些,您会注意到第一个(同步)示例, result.length 将在 'Hello World' 行之前打印出来。在第二个(异步)示例中, result.length 将(很可能)在“Hello World”行之后打印。

That's because in the second example, the database.queryis run asynchronously in the background, and the script continues straightaway with the "Hello World". The console.log(result.length)is only executed when the database query has completed.

这是因为在第二个示例中,database.query是在后台异步运行的,并且脚本会直接继续执行“Hello World”。在console.log(result.length)当数据库查询完成时才会执行。

回答by Jay

First, I realize I am late in answering this question.

首先,我意识到我回答这个问题晚了。

Before discussing synchronous and asynchronous, let us briefly look at how programs run.

在讨论同步和异步之前,让我们简要地看看程序是如何运行的。

In the synchronouscase, each statement completesbefore the next statement is run. In this case the program is evaluated exactly in order of the statements.

同步情况下,每条语句在下一条语句运行之前完成。在这种情况下,程序会按照语句的顺序进行评估。

This is how asynchronousworks in JavaScript. There are two parts in the JavaScript engine, one part that looks at the code and enqueues operations and another that processes the queue. The queue processing happens in one thread, that is why only one operation can happen at a time.

这就是异步在 JavaScript 中的工作方式。JavaScript 引擎中有两部分,一部分查看代码并将操作排入队列,另一部分处理队列。队列处理发生在一个线程中,这就是为什么一次只能发生一个操作。

When an asynchronous operation (like the second database query) is seen, the code is parsed and the operation is put in the queue, but in this case a callback is registered to be run when this operation completes. The queue may have many operations in it already. The operation at the front of the queue is processed and removed from the queue. Once the operation for the database query is processed, the request is sent to the database and when complete the callback will be executed on completion. At this time, the queue processor having "handled" the operation moves on the next operation - in this case

当看到异步操作(如第二个数据库查询)时,将解析代码并将操作放入队列,但在这种情况下,会注册回调以在此操作完成时运行。队列中可能已经有许多操作。队列前端的操作被处理并从队列中移除。处理完数据库查询的操作后,将请求发送到数据库,完成后将在完成时执行回调。此时,已“处理”该操作的队列处理器将继续进行下一个操作——在本例中

    console.log("Hello World"); 

The database query is still being processed, but the console.log operation is at the front of the queue and gets processed. This being a synchronous operation gets executed right away resulting immediately in the output "Hello World". Some time later, the database operation completes, only then the callback registered with the query is called and processed, setting the value of the variable result to rows.

数据库查询仍在处理中,但 console.log 操作位于队列的前面并被处理。这是一个同步操作,立即执行,结果立即输出“Hello World”。一段时间后,数据库操作完成,然后调用并处理向查询注册的回调,将变量结果的值设置为行。

It is possible that one asynchronous operation will result in another asynchronous operation, this second operation will be put in the queue and when it comes to the front of the queue it will be processed. Calling the callback registered with an asynchronous operation is how JavaScript run time returns the outcome of the operation when it is done.

一个异步操作可能会导致另一个异步操作,这第二个操作将被放入队列中,当它到达队列的前面时,它将被处理。调用异步操作注册的回调是 JavaScript 运行时在操作完成时返回操作结果的方式。

A simple method of knowing which JavaScript operation is asynchronous is to note if it requires a callback - the callback is the code that will get executed when the first operation is complete. In the two examples in the question, we can see only the second case has a callback, so it is the asynchronous operation of the two. It is not always the case because of the different styles of handling the outcome of an asynchronous operation.

了解哪个 JavaScript 操作是异步的一个简单方法是注意它是否需要回调 - 回调是第一个操作完成时将执行的代码。在题中的两个例子中,我们可以看到只有第二种情况有回调,所以是两者的异步操作。由于处理异步操作结果的方式不同,情况并非总是如此。

To learn more, read about promises. Promises are another way in which the outcome of an asynchronous operation can be handled. The nice thing about promises is that the coding style feels more like synchronous code.

要了解更多信息,请阅读 Promise。Promise 是另一种处理异步操作结果的方式。Promise 的好处在于,它的编码风格更像是同步代码。

Many libraries like node 'fs', provide both synchronous and asynchronous styles for some operations. In cases where the operation does not take long and is not used a lot - as in the case of reading a config file - the synchronous style operation will result in code that is easier to read.

许多库(如节点“fs”)为某些操作提供同步和异步样式。在操作不需要很长时间并且不经常使用的情况下 - 如在读取配置文件的情况下 - 同步样式操作将导致代码更易于阅读。

回答by related

In the synchronous case, the console.log command is not executed until the SQL query has finished executing.

在同步情况下,console.log 命令直到 SQL 查询执行完毕后才会执行。

In the asynchronous case, the console.log command will be directly executed. The result of the query will then be stored by the "callback" function sometime afterwards.

在异步情况下,将直接执行console.log 命令。查询的结果将在之后的某个时间由“回调”函数存储。

回答by thebreiflabb

The main difference is with asynchronous programming, you don't stop execution otherwise. You can continue executing other code while the 'request' is being made.

主要区别在于异步编程,否则您不会停止执行。您可以在发出“请求”时继续执行其他代码。

回答by Anton Chan

The function makes the second one asynchronous.

该函数使第二个异步。

The first one forces the program to wait for each line to finish it's run before the next one can continue. The second one allows each line to run together (and independently) at once.

第一个强制程序等待每一行完成它的运行,然后才能继续下一行。第二个允许每条线同时(并且独立地)运行。

Languages and frameworks (js, node.js) that allow asynchronous or concurrency is great for things that require real time transmission (eg. chat, stock applications).

允许异步或并发的语言和框架(js、node.js)非常适合需要实时传输的事物(例如聊天、股票应用程序)。

回答by Neeraj Bansal

Sync Programming

同步编程

Programming languages like C, C#, Java are sync programming, what so ever you write will be execute in order of your writing.

C、C#、Java 等编程语言是同步编程,您编写的任何内容都将按照您编写的顺序执行。

-GET DATA FROM SQL.
//Suppose fetching data take 500 msec

-PERFORM SOME OTHER FUNCTION.
//Performing some function other will take 100 msec, but execution of other 
//task start only when fetching of sql data done (i.e some other function 
//can execute only after first in process job finishes).

-TOTAL TIME OF EXECUTION IS ALWAYS GREATER THAN (500 + 100 + processing time) 
msec

Async

异步

NodeJs comes up with async feature, it's non-blocking in nature, suppose in any I/O task which is taking time (fetching, writing, reading), nodejs won't kept idle and wait for the task to be finish, it'll start executing next tasks in the queue, and whenever that time taking task completed it will notify using callback. Following example will help:

NodeJs 提供了异步特性,它本质上是非阻塞的,假设在任何需要时间的 I/O 任务(获取、写入、读取)中,nodejs 不会保持空闲并等待任务完成,它将开始执行队列中的下一个任务,每当该任务完成时,它将使用回调通知。以下示例将有所帮助:

//Nodejs uses callback pattern to describe functions.
//Please read callback pattern to understand this example

//Suppose following function (I/O involved) took 500 msec
function timeConsumingFunction(params, callback){
  //GET DATA FROM SQL
  getDataFromSql(params, function(error, results){
    if(error){
      callback(error);
    }
    else{
      callback(null, results);
    }
  })
}

//Suppose following function is non-blocking and took 100 msec
function someOtherTask(){
  //some other task
  console.log('Some Task 1');
  console.log('Some Task 2');
}

console.log('Execution Start');

//Start With this function
timeConsumingFunction(params, function(error, results){
    if(error){
      console.log('Error')
    }
    else{
      console.log('Successfull'); 
    }
  })

//As (suppose) timeConsumingFunction took 500 msec, 
//As NodeJs is non-blocking, rather than remain idle for 500 msec, it will start 
//execute following function immediately
someOtherTask();

In Short, Output is as:

简而言之,输出为:

Execution Start
//Roughly after 105 msec (5 msec it'll take in processing)
Some Task 1
Some Task 2
//Roughly After 510 msec
Error/Successful //depends on success and failure of DB function execution

Difference is clear where sync will definitely take more than 600 (500 + 100 + processing time) msec, async saves time.

区别很明显,同步肯定需要超过 600(500 + 100 + 处理时间)毫秒,异步节省时间。

回答by Vetrivel Chinnasamy

Synchronous functions are blocking while asynchronous functions are not. In synchronous functions, statements complete before the next statement is run. In this case, the program is evaluated exactly in order of the statements and execution of the program is paused if one of the statements take a very long time.

同步函数是阻塞的,而异步函数不是。在同步函数中,语句在下一个语句运行之前完成。在这种情况下,程序会按照语句的顺序进行精确评估,如果其中一个语句花费了很长时间,则程序的执行将暂停。

Asynchronous functions usually accept a callback as a parameter and execution continue on the next line immediately after the asynchronous function is invoked. The callback is only invoked when the asynchronous operation is complete and the call stack is empty. Heavy duty operations such as loading data from a web server or querying a database should be done asynchronously so that the main thread can continue executing other operations instead of blocking until that long operation to complete (in the case of browsers, the UI will freeze).

异步函数通常接受回调作为参数,并且在调用异步函数后立即在下一行继续执行。回调仅在异步操作完成且调用堆栈为空时调用。诸如从 Web 服务器加载数据或查询数据库之类的繁重操作应该异步完成,以便主线程可以继续执行其他操作而不是阻塞,直到完成那个长时间的操作(在浏览器的情况下,UI 将冻结) .

Orginal Posted on Github: Link

原文发布在 Github:链接

回答by Willem van der Veen

Asynchronous programming in JS:

JS异步编程:

Synchronous

同步

  • Stops execution of further code until this is done.
  • Because it this stoppage of further execution, synchronous code is called 'blocking'. Blocking in the sense that no other code will be executed.
  • 停止执行进一步的代码,直到完成。
  • 因为它会停止进一步执行,所以同步代码被称为“阻塞”。阻塞的意思是不会执行其他代码。

Asynchronous

异步

  • Execution of this is deferred to the event loop, this is a construct in a JS virtual machine which executes asynchronous functions (after the stack of synchronous functions is empty).
  • Asynchronous code is called non blocking because it doesn't block further code from running.
  • this 的执行被推迟到事件循环中,这是一个 JS 虚拟机中执行异步函数的构造(在同步函数堆栈为空之后)。
  • 异步代码被称为非阻塞,因为它不会阻止更多的代码运行。

Example:

例子:

// This function is synchronous
function log(arg) {
    console.log(arg)
}

log(1);

// This function is asynchronous
setTimeout(() => {
    console.log(2)
}, 0);

log(3)

  • The example logs 1, 3, 2.
  • 2 is logged last because it is inside a asynchronous function which is executed after the stack is empty.
  • 该示例记录 1、3、2。
  • 2 被最后记录,因为它在一个异步函数中,该函数在堆栈为空后执行。