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


Я читал 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");

Я получаю то, что они должны делать, они запрашивают базу данных, чтобы получить ответ на запрос. А потом console.log('Hello world').

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

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

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

8 163

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

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

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

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

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

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

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

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

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

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". Элемент console.log(result.length) выполняется только после завершения запроса к базе данных.

во-первых, я понимаю, что опоздал с ответом на этот вопрос.

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

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

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

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

    console.log("Hello World"); 

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

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

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

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

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

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

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

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

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

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

языки и фреймворки (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 + обрабатывая время) мсек, асинхронность сохраняет время.