Является ли Javascript синхронным (блокирующим) или асинхронным (неблокирующим) по умолчанию

Я пытаюсь понять асинхронные функции и обратные вызовы Javascript.

Я застрял на концепции функций обратного вызова, где я читаю в некоторых местах: они используются для последовательного выполнения кода (в основном в контексте jquery, например, анимация) и в некоторых местах специально в контексте Nodejs; они используются для параллельного асинхронного выполнения и предотвращения блокировки кода.

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

или это зависит исключительно от того места, где вы вызываете/размещаете функцию обратного вызова в своем коде? .

Спасибо,

P.S: я боюсь, что этот вопрос будет близок к субъективному, но все же я могу ожидать конкретного ответа на него (возможно, несколько примеров)

Редактировать: на самом деле это пример из Интернета, который вызывает у меня двусмысленность:

function do_a(){
  // simulate a time consuming function
  setTimeout( function(){
    console.log( '`do_a`: this takes longer than `do_b`' );
  }, 1000 );
}

function do_b(){
  console.log( '`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`' );
}

do_a();
do_b();

Результат

`do_b`: this is supposed to come out after `do_a` but it comes out before `do_a`
`do_a`: this takes longer than `do_b`

когда JS является последовательным, тогда do_b всегда должен идти после do_a, согласно моему пониманию.


person static void main    schedule 13.05.2013    source источник
comment
JavaScript есть JavaScript; это зависит от контекста, использования, движка и т. д.   -  person Dave Newton    schedule 13.05.2013
comment
Можете ли вы предоставить пример кода, в котором вы не уверены, является ли он блокирующим или неблокирующим?   -  person Matt    schedule 13.05.2013
comment
JavaScript в целом синхронен, но setTimeout асинхронен по определению. Вот хорошее руководство по этому вопросу: developer.mozilla.org/en-US /docs/DOM/window.setTimeout   -  person Colin DeClue    schedule 13.05.2013


Ответы (3)


Ядро JavaScript в значительной степени синхронно, поскольку функции полностью выполняют свою задачу до завершения. До появления AJAX только setTimeout и setInterval обеспечивали асинхронное поведение.

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

Затем появился AJAX с его обращениями к серверу. Эти вызовы можно было настроить как синхронные, но разработчики обычно предпочитали асинхронные вызовы и использовали методы обратного вызова для их реализации.

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

Теперь мы видим Deferreds и Promises в миксе. Это объекты, которые представляют значение длительной операции и предоставляют API для обработки этого значения, когда оно поступает.

NodeJS склоняется к асинхронному подходу ко многим вещам; это правда. Однако это скорее дизайнерское решение с их стороны, а не присущая JS асинхронность.

person Dancrumb    schedule 13.05.2013

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

Синхронный код:

console.log('a');
console.log('b');

Асинхронный код:

console.log('a');
setTimeout(function() {
    console.log('b');
}, 1000);
setTimeout(function() {
    console.log('c');
}, 1000);
setTimeout(function() {
    console.log('d');
}, 1000);
console.log('e');

Это выводит: a e b c d

person Deepak Sisodiya    schedule 10.05.2015
comment
Что означает блокировка в этом контексте? - person Sandeepan Nath; 14.03.2016
comment
@SandeepanNath Возможно, вы уже поняли это, но для будущих посетителей: блокировка относится к последовательной обработке. Делать одно дело за раз. С другой стороны, неблокирующий код (асинхронный) может выполняться параллельно (или многопоточно). Преимущество в том, что это может быть быстрее. - person Connor; 28.06.2019

В длительных процессах node используйте process.nextTick() для постановки в очередь функций/обратных вызовов. Обычно это делается в API узла, и если вы не программируете (вне API) что-то, что блокирует или работает долго, это не сильно на вас влияет. Ссылка ниже должна объяснить это лучше, чем я могу.

howtonode process.nextTick()

jQuery AJAX также принимает обратные вызовы и, например, закодирован так, чтобы не ждать ответов сервера, прежде чем перейти к следующему блоку кода. Он просто запоминает функцию для запуска, когда сервер отвечает. Это основано на объекте XMLHTTPRequest, предоставляемом браузерами. Объект XHR запомнит функцию для обратного вызова при возврате ответа.

setTimeout(fn, 0) javascript запустит функцию, как только стек вызовов станет пустым (следующий свободный тик), который можно использовать для создания асинхронных функций. setTimeout(fn, 0) вопрос о stackoverflow

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

Отложенный объект Jquery Еще одна хорошая ссылка на асинхронные возможности jQuery. Погуглив, вы можете найти информацию о том, как работает jQuery Deferred, чтобы получить больше информации.

person Adam    schedule 13.05.2013