Почему функции обратного вызова позволяют нам делать что-то асинхронно в Javascript?

Я читал, что обратные вызовы делают JavaScript асинхронным. Но я не уверен, понял ли я объяснение. Вот что я получаю

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

Это правда? Спасибо


person GniruT    schedule 08.10.2015    source источник
comment
Вы знаете, что такое обратный вызов? Потому что они позволяют выполнять асинхронные операции на всех языках, а не только на Javascript.   -  person lilezek    schedule 08.10.2015
comment
См. Здесь stackoverflow.com/questions/14220321/   -  person Jasen    schedule 08.10.2015
comment
Нет, я пытаюсь понять это для JS. Но я не знаю, правильно ли это утверждение   -  person GniruT    schedule 08.10.2015


Ответы (2)


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

Например, Javascript array.forEach() использует обратный вызов, но он не является асинхронным. Итак, асинхронные операции являются асинхронными, потому что их базовая реализация неблокирующая. Вы начинаете операцию с вызова функции, операция выполняется в фоновом режиме, а остальная часть вашего кода продолжает выполняться. Между тем, когда асинхронная операция завершается, она обычно должна сообщить вашему коду, что она выполнена, и, возможно, сообщить некоторые результаты. Функция обратного вызова - это выбранный механизм для сообщения о завершении асинхронной операции.

Я читал, что обратные вызовы делают JavaScript асинхронным.

Нет, это не совсем так. Обратные вызовы также могут использоваться с синхронными операциями. То, что вы используете обратный вызов, не делает ничего асинхронным. Базовая реализация операции в собственном коде должна быть асинхронной (например, вызов Ajax или другая сетевая операция). Обратные вызовы используются для передачи результатов асинхронных операций. У них также есть много других неасинхронных применений. Таким образом, обратный вызов - это всего лишь один из инструментов, используемых в асинхронной операции, а обратный вызов - это инструмент, имеющий множество других применений. Вы не можете сказать callback === asynchronous.

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

Трудно точно сказать, что вы имеете в виду, но мне это кажется неправильным. При использовании асинхронных операций код обычно не выполняется в порядке, указанном в файле. Например, если вы сделали это:

console.log("async start");
callSomeAsyncOperation(function(result) {
    console.log("async done");
});
console.log("I'm here now");

Вы увидите это в журнале:

async start
I'm here now
async done

Объяснение обратных вызовов и очередей событий

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

При написании Javascript вы часто будете регистрировать и обрабатывать событие для события. То, как это работает в Javascript, заключается в том, что вы говорите, какое событие вас интересует (что также может включать указание некоторой другой информации, например, какой объект вы ищете для событий), а затем вы передаете это ссылку на функцию. По сути, вы сообщаете механизму Javascript, что хотите, чтобы он вызывал ссылку на вашу функцию при возникновении этого события. Этот тип ссылки на функцию называется «обратным вызовом». Это обычная функция, но контекст, в котором она используется, называется «обратным вызовом», потому что какой-то другой код в какой-то момент в будущем «перезвонит вам», выполнив вашу функцию. Затем вы можете разместить соответствующий код в этой ссылке на функцию (внутри этой функции обратного вызова), который может реагировать на это событие. В зависимости от типа события вам могут звонить только один раз или он может звонить вам каждый раз, когда это событие происходит.

Вы можете узнать больше о том, как эта очередь событий и обратные вызовы работают в этих справочниках:

Запустить произвольный код в ожидании обратного вызова в узле?

код блокировки на неблокирующем HTTP-сервере

Скрытые потоки в Javascript / Node, которые никогда не выполняют пользовательский код: возможно ли это, и если да, может ли это привести к загадочной возможности для состояния гонки?

Как JavaScript обрабатывает ответы AJAX в фоновом режиме? (написано про браузер, но концепция та же)

person jfriend00    schedule 08.10.2015
comment
возможно, разрешить - лучший выбор слов, чем сделать - person Keith Nicholas; 08.10.2015
comment
нет, обратные вызовы позволяют вам писать асинхронный код, поскольку это механизм отложенного выполнения, это не единственный способ, а способ, которым использует javascript. Вам не нужно ничего в базовом коде, чтобы быть асинхронным, вы можете написать свою собственную асинхронную систему на javascript, если хотите. - person Keith Nicholas; 08.10.2015
comment
конечно можно :) родной материал предназначен только для внешних событий вне языка, и они действительно должны быть неблокирующими. Но в самом простом случае ... gist.github.com/keithn/fb0683a3df9fc3b8b2c7. Именно так я делаю асинхронные вещи во встроенном мире. - person Keith Nicholas; 08.10.2015
comment
все, что мне нужно, это привязки к родному миру, и я мог бы генерировать события из более интересных вещей. - person Keith Nicholas; 08.10.2015
comment
добавлена ​​функция setinterval ... просто для удовольствия :) - person Keith Nicholas; 08.10.2015
comment
это именно то, как работает javascript, вам не нужен таймер, функционально он тот же, я отлично реализовал setinterval. Вот как однопоточные вещи достигают асинхронности. Очередь событий с отправкой через обратные вызовы. Все, что может достичь внешний таймер, - это лучшее использование процессора и лучшее время, вот и все. В остальном это то же самое. Вот почему обратные вызовы допускают асинхронность, и это наиболее распространенный способ, которым люди реализуют его в системе, у которой нет средств для этого. (как во встроенных системах). - person Keith Nicholas; 08.10.2015
comment
Я просто оставлю свой. На всякий случай, jfriend00 не понимал, как можно реализовать асинхронность с чистым javascript. - person Keith Nicholas; 08.10.2015
comment
@GniruT - это ответ на ваш вопрос? - person jfriend00; 15.10.2015

Прежде всего давайте разберемся, что такое обратный вызов ( по определению):

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


Теперь, говоря о Javascript, не всегда обратный вызов является асинхронным. Например:

function syncOperation(callback) {
  callback();
}

syncOperation(function() {
  console.log('a');
  console.log('b');
});

console.log('c');

Этот обратный вызов является синхронным, поскольку он не выполняет никаких асинхронных операций. Если вы откроете консоль и запустите приведенный выше код, вы увидите, что он будет регистрировать a, затем b, затем c.


Теперь давайте посмотрим на асинхронный пример:

function asyncOperation(callback) {
  setTimeout(callback, 0);
}

asyncOperation(function() {
  console.log('a');
  console.log('b');
});

console.log('c');

Сначала вы увидите c, затем a и b. Это потому, что функция setTimeout выполняется асинхронно.

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

var a = 'text';
setTimeout(function() { a = 'new text'; }, 0);
console.log(a);

В консоли вы увидите text, потому что он будет запущен до того, как переменная будет изменена.

person Buzinas    schedule 08.10.2015