В чем разница между синхронным и асинхронным программированием (в узел.Яш)

Я читал nodebeginner И я наткнулся на следующие два фрагмента кода.

первый:

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

второй:

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

Я получаю то, что они должны делать, они запрашивают базу данных, чтобы получить ответ на запрос. А потом ... --2-->.

первый предположительно синхронный код. А второй-асинхронный код.

разница между двумя частями очень смутно для меня. Каким будет результат?

гуглить по асинхронному программированию мне тоже не помогло.

8 ответов


разница в том, что в первый пример программа будет блокировать в первой строке. Следующая строка (console.log) придется подождать.

на второй пример на console.log будет выполняться во время обработки запроса. То есть запрос будет обрабатываться в фоновом режиме, в то время как ваша программа делает другие вещи, и как только данные запроса будут готовы, вы будете делать с ним все, что захотите.

так, в двух словах: первый пример будет блокировать, в то время как второй не будет.

вывод следующих двух примеров:

// 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");

будет:

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

Примечание
В то время как сам узел однопоточным, есть некоторые задачи, которые могут выполняться параллельно. Например, операции файловой системы выполняются в другом процессе.

вот почему узел может выполнять асинхронные операции: один поток выполняет операции файловой системы, в то время как основной поток узла продолжает выполнять ваш код javascript. В управляемом событиями сервере, таком как Node, поток файловой системы уведомляет основной поток узла о некоторых событиях, таких как завершение, сбой или прогресс, вместе с любыми данными, связанными с этим событием (например, результатом запроса базы данных или сообщения об ошибке), и основной поток узла решает, что делать с этими данными.

вы можете подробнее об этом здесь: как однопоточная модель неблокирующее IO работает в узле.js


разница между этими двумя подходами заключается в следующем:

синхронно так: Он ожидает завершения каждой операции, после чего выполняет только следующую операцию. Для запроса: The console.log() команда не будет выполнена, пока & если запрос не завершит выполнение, чтобы получить весь результат из базы данных.

асинхронный образом: Он никогда не ждет завершения каждой операции, а выполняет все операции в первом ходе только. Результат каждой операции будет обработан, как только результат будет доступен. Для запроса: The console.log() команда будет выполнена вскоре после Database.Query() метод. В то время как запрос к базе данных выполняется в фоновом режиме и загружает Результат после завершения извлечения данных.

варианты использования

  1. Если ваши операции не делают очень тяжелый подъем, как запрос огромных данных из БД, то идти вперед с синхронным способом в противном случае асинхронным путь.

  2. асинхронным способом вы можете показать некоторый индикатор прогресса пользователю, а в фоновом режиме вы можете продолжить свои тяжелые работы. Это идеальный сценарий для приложений GUI.


это станет немного более ясным, если вы добавите строку в оба примера:

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

второй:

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

попробуйте запустить их, и вы заметите, что первый (синхронный) пример, результат.длина будет распечатана перед строкой "Hello World". Во втором (асинхронном) примере результат.длина (скорее всего) будет напечатана после строки "Hello World".

это потому, что во втором примере database.query запускается асинхронно в фоновом режиме, и сценарий продолжается сразу с "Hello World". The console.log(result.length) выполняется только после завершения запроса к базе данных.


прежде чем обсуждать синхронность и асинхронность, давайте кратко рассмотрим, как работают программы.

на синхронно случае, каждое заявление завершается перед запуском следующего оператора. В этом случае программа оценивается точно в порядке заявления.

Это как асинхронные работает в JavaScript. В JavaScript есть две части двигатель, одна часть, которая смотрит на код и запрашивает операции, а другая, которая обрабатывает очередь. Обработка очереди происходит в одном потоке, поэтому одновременно может выполняться только одна операция.

когда асинхронная операция (например, второй запрос базы данных) видна, код анализируется и операция помещается в очередь, но в этом случае обратный вызов регистрируется для запуска по завершении этой операции. В очереди может быть уже много операций. Операция на очередь обрабатывается и удаляется из очереди. Как только операция для запроса базы данных обработана, запрос отправляется в базу данных и по завершении обратного вызова будет выполнен. В это время процессор очереди, "обработав" операцию, переходит к следующей операции-в этом случае

    console.log("Hello World"); 

запрос базы данных все еще обрабатывается, но консоль.операция log находится в передней части очереди и обрабатывается. Это синхронная операция выполняется сразу же, что немедленно приводит к выходу "Hello World". Через некоторое время операция базы данных завершается, только после этого вызывается и обрабатывается обратный вызов, зарегистрированный в запросе, устанавливая значение переменной result в строки.

вполне возможно, что одна асинхронная операция приведет к другой асинхронной операции, вторая операция будет поставить в очередь и, когда дело доходит до начала очереди будет обработан. Вызов обратного вызова, зарегистрированного в асинхронной операции, - это то, как время выполнения JavaScript возвращает результат операции, когда она выполнена.

простой способ узнать, какая операция JavaScript является асинхронной, - это отметить, требует ли она обратного вызова - обратный вызов-это код, который будет выполнен после завершения первой операции. В двух примерах в вопросе мы видим, что только второй случай имеет обратный вызов, поэтому это асинхронная операция двух. Это не всегда это происходит из-за разных стилей обработки результата асинхронной операции.

чтобы узнать больше, прочитайте про обещания. Обещания-это еще один способ обработки результата асинхронной операции. Хорошая вещь о обещаниях заключается в том, что стиль кодирования больше похож на синхронный код.

многие библиотеки, такие как узел "fs", предоставляют синхронные и асинхронные стили для некоторых операций. В случаях, когда операция не займет много времени и не используется много - как в случае чтения файла конфигурации - синхронная операция стиля приведет к коду, который легче читать.


в синхронном случае, консоли.команда log не выполняется до завершения выполнения SQL-запроса.

в асинхронном случае, консоли.команда log будет выполнена напрямую. Затем результат запроса будет сохранен функцией "callback" некоторое время спустя.


основное отличие заключается в асинхронном программировании, в противном случае вы не останавливаете выполнение. Вы можете продолжить выполнение другого кода во время выполнения "запроса".


функция делает второй асинхронный.

первый заставляет программу ждать завершения каждой строки, прежде чем следующая может продолжаться. Второй позволяет каждой линии работать вместе (и независимо) одновременно.

языки и фреймворки (js, node.js), которые позволяют асинхронный или параллелизм отлично подходит для вещей, которые требуют передачи в реальном времени (например. чат, фондовые приложения).


Синхронизация Программирования

языки программирования, такие как 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

асинхронные

NodeJs придумывает асинхронную функцию, она не блокируется по своей природе, предположим, что в любой задаче ввода-вывода, которая занимает время (извлечение, запись, чтение), 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();

короче, вывод:

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

разница ясна где синхронизация определенно примет больше чем 600 (500 + 100 + обрабатывая время) мсек, асинхронность сохраняет время.