Является ли Javascript синхронным (блокирующим) или асинхронным (неблокирующим) по умолчанию
Я пытаюсь понять асинхронные функции и обратные вызовы Javascript.
Я застрял в концепции функций обратного вызова, где я читаю в некоторых местах: они используются для последовательного выполнения кода (в основном в контексте jquery, например, animate) и в некоторых местах, особенно в контексте Nodejs; они используются для асинхронного параллельного выполнения и предотвращения блокировки кода.
Так может какой-нибудь эксперт в этой теме, пожалуйста, пролить свет на это и прояснить этот вопрос (примеры??). чтобы я мог подумать об использовании функции обратного вызова
или это зависит исключительно от места, где вы вызываете / размещаете функцию обратного вызова в вашем коде? ,
Спасибо,
PS: я боюсь, что этот вопрос будет близок как субъективный, но все же я могу ожидать конкретного ответа на это (возможно, некоторые примеры)
Редактировать: на самом деле это пример из Интернета, который делает меня неоднозначным:
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, согласно моему пониманию.
5 ответов
Ядро JavaScript в значительной степени синхронно, так как функции полностью завершают свою задачу до завершения. До появления AJAX на самом деле только setTimeout и setInterval обеспечивали асинхронное поведение.
Однако легко забыть, что обработчики событий являются, по сути, асинхронным кодом. Присоединение обработчика не вызывает код обработчика, и этот код не выполняется до некоторого неизвестного времени в будущем.
Затем появился AJAX с его вызовами на сервер. Эти вызовы могут быть настроены на синхронность, но разработчики обычно предпочитают асинхронные вызовы и используют методы обратного вызова для их реализации.
Затем мы увидели распространение библиотек JS и наборов инструментов. Они стремились к гомогенизации различных реализаций браузеров и основывались на подходе обратного вызова для асинхронного кода. Вы также начали видеть намного больше синхронных обратных вызовов для таких вещей, как итерация массива или обработка результатов запроса CSS.
Теперь мы видим отсрочку и обещания в миксе. Это объекты, которые представляют значение длительной операции и предоставляют API для обработки этого значения при его получении.
NodeJS склоняется к асинхронному подходу ко многим вещам; это правда. Однако это скорее проектное решение с их стороны, нежели какая-либо присущая JS асинхронная природа.
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
В узле используются длительные процессы process.nextTick()
поставить в очередь функции / обратные вызовы. Обычно это делается в API узла, и если ваше программирование (за исключением API) с чем-то, что блокирует, или код, который долго выполняется, то на самом деле это вас не сильно затронет. Ссылка ниже должна объяснить это лучше, чем я могу.
JQuery AJAX также принимает обратные вызовы и, таким образом, кодируется так, чтобы не ждать ответов сервера, прежде чем перейти к следующему блоку кода. Он просто запоминает функцию, запускаемую при ответе сервера. Это основано на объекте XMLHTTPRequest, который предоставляют браузеры. Объект XHR запомнит функцию, которую нужно вызвать обратно, когда ответ вернется.
setTimeout(fn, 0)
javascript будет запускать функцию, когда стек вызовов пуст (следующий доступный свободный тик), который можно использовать для создания асинхронных функций. setTimeout (fn, 0) вопрос о переполнении стека
Чтобы избавиться от асинхронных возможностей javascript, нужно иметь дело как со средами, в которых они запрограммированы, так и с самим javascript. Вы не получаете никакого волшебства, просто используя множество вызовов функций и обратных вызовов, если вы не используете какой-либо API/ скрипт.
Jquery Deferred Object Еще одна хорошая ссылка для асинхронных возможностей jQuery. Google может найти вам информацию о том, как jQuery Deferred работает также для получения дополнительной информации.
В JavaScript термин «асинхронный» обычно относится к коду, который выполняется, когда стек вызовов пуст, и механизм выбирает задание для выполнения из одной из своих очередей заданий.
Как только код выполняется, он представляет собой синхронную последовательность выполнения, которая продолжается до тех пор, пока стек вызовов снова не станет пустым. Эта последовательность выполнения не будет прервана событиями для выполнения какого-либо другого кода JavaScript (когда мы отбрасываем Web Workers). Другими словами, в одной среде JavaScript нет упреждающего параллелизма.
Пока выполняется синхронное выполнение, события могут быть зарегистрированы как задания в некоторых очередях заданий, но механизм не будет обрабатывать их до первого правильного выполнения того, что находится в стеке вызовов. Только когда стек вызовов пуст, движок заметит очереди заданий, выберет одно в соответствии с приоритетом и выполнит его (и это называется асинхронным).
Обратные вызовы
Обратные вызовы могут быть синхронными или асинхронными — это действительно зависит от того, как они вызываются.
Например, здесь обратный вызов выполняется синхронно:
new Promise(function (resolve) { /* .... */ });
А здесь обратный вызов выполняется асинхронно:
setTimeout(function () { /* ... */ });
Это действительно зависит от функции, которая принимает обратный вызов в качестве аргумента; как он справляется с окончательным вызовом этого обратного вызова.
Способы заставить код выполняться асинхронно
Основной язык ECMAScript не предлагает много способов сделать это. Известные из них предлагаются через другие API, такие как веб-API, которые не являются частью основного языка (
Основные предложения ECMAScript
Он также предлагает прослушивание, когда сборщик мусора собирается собрать объект, с
Веб-воркеры
Веб-воркеры будут выполняться в отдельной среде выполнения с собственным стеком вызовов. Здесь возможен упреждающий параллелизм. Когда термин асинхронный используется в мире JavaScript, он обычно не относится к такому типу параллелизма, хотя связь с Web Worker происходит через асинхронные функции обратного вызова.
Javascript по умолчанию является «синхронным», это веб-API, которые обрабатывают «асинхронное» поведение.
Что касается примера setTimeout,
console.log(...) в глобальной области работает сразу, в то время как те внутренние функции, обернутые внутри setTimeout, ждут внутри очереди обратного вызова только для того, чтобы вернуться в стек вызовов после готовности. Таким образом, они требуют времени. Кроме того, указанное время не является точным, а является минимальным временем, после которого этот фрагмент кода может выполняться в любое время.
Спасибо !