2016-11-30 10 views
7

Я не могу понять, как работает следующий код. Почему «1» после «b», но «h» после «3»? Должен ли порядок: a, b, 1, 2, h, 3? В какой-то статье говорилось, что различие между «очередь циклов событий» и «очередь заданий» приводит к следующему результату. Но как? Я прочитал спецификацию ECMAScript 2015 - 8.4 Jobs and Job Queues, желая узнать, как работает Promise'job, но это меня смущает. Кто-нибудь может мне помочь? Спасибо!В чем разница между «очередью цикла событий» и «очередью заданий»?

var promise = new Promise(function(resolve, reject) {resolve(1)}); 
promise.then(function(resolve) {console.log(1)}); 
console.log('a'); 
promise.then(function(resolve) {console.log(2);}); 
setTimeout(function() {console.log('h')}, 0); 
promise.then(function(resolve) {console.log(3)}); 
console.log('b'); 

// a 
// b 
// 1 
// 2 
// 3 
// h 

Я знаю Promise асинхронный, но обратного вызова SetTimeout (..) асинхронной операции всегда после асинхронной операции Promise,. Зачем?

+0

Promise является асинхронными - даже встроенным синхронным ищут код, как это, .then вызываются асинхронно - это то, что обещает сделать –

ответ

5

Почему «1» после «b»?

По спецификации обещания, все обещания .then() обработчики называются асинхронно ПОСЛЕ того, как текущий поток JS завершился. Таким образом, оба a и b, которые выполняются синхронно как часть текущего JS, будут выполняться перед любыми обработчиками .then(), так что 1 всегда будет после a и b.

Некоторые интересные данные: T asks, microtasks, queues and schedules и What is the order of execution in javascript promises и Writing a JavaScript framework - Execution timing, beyond setTimeout.


Там некоторые хорошие советы здесь в этой теме: Promises wiggle their way between nextTick and setImmediate:

Я бы не рекомендовал полагаться на точном порядке исполнения нецепных событий. Если вы хотите контролировать порядок выполнения - , переупорядочивайте обратные вызовы таким образом, чтобы тот, который вы хотите выполнить , выполненный позже, зависит от того, который вы хотите выполнить раньше, или реализуйте очередь (которая делает то же самое за капотом).

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

+1

почему 'h' после' 3' : p –

+0

@JaromandaX, скорее всего, очередь заданий реализации JS имеет более высокий приоритет, чем очереди событий, реализованные браузерами. Но не совсем уверен. – MinusFour

+0

@JaromandaX - Это немного другой вопрос, чем спросил ОП. Я должен был бы провести некоторое исследование, чтобы выяснить, является ли это спецификацией или специфично для реализации, основываясь на том, как '.then()' обработчики находятся в очереди или 'setTimeout()' события. – jfriend00

3

В HTML-терминах event loop для страницы или набора страниц из того же домена может иметь несколько task queues. Задачи из того же task source всегда идут в одну очередь, при этом браузер выбирает, какую очередность задач использовать следующим образом.

Задачи для запуска обратных вызовов таймера поступают из timer task source и идут в одной очереди. Назовем эту очередь задачей очереди «A».

Спецификация ECMAscript 2015 (ES6) требует выполнения задач для выполнения обратных вызовов реакции Promise для формирования собственной очереди заданий, которая называется "PromiseJobs". Спецификации ECMAscript и HTML не используют один и тот же язык, поэтому давайте условно приравняем ECMA «Promise Job queue» с HTML очередью задач «B» в браузере - по крайней мере, другая очередь для той, которая используется таймерами.

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

Именно поэтому «h» заносится в журнал последним. Promise then призывает выполнять выполненные обещания разместить задания в очереди обещаний, которые выполняются с более высоким приоритетом, чем обратные вызовы по таймеру. Очередь обещаний становится пустой после того, как выполнено console.log(3), что позволяет выполнить обратный вызов таймера.


Расширенный

ECMAScript опекуны решили не использовать терминологию HTML5 или описание очередей задач в их спецификации, потому что ECMAScript может работать в нескольких средах, чем просто HTML-браузеров.

Собственная реализация очередей обещаний может использовать очередь «микрозадачей» вместо отдельной целевой очереди задач обещания. Задачи с микро-очередью запускаются только после текущего потока сценариев, и все задачи, ранее добавленные в микро-очередь, завершены.

Деталь очередности микрозадачей не требуется для понимания обещаний.

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

0

Я нашел, что это легко понять для кого-то нового для JS.

Это копия паста из @ getify книжном

использовать метафору: очередь цикла события, как ездить парк развлечений, где, как только вы закончите поездку, вы должны идти к задней части чтобы снова ехать. Но очередь «Работа» - это как завершение поездки, но затем резка в линию и возвращение обратно.

очередь цикл обработка событий - для всех асинхронных обратных вызовов, кроме обещаний, ч

очереди заданий - для всех асинхронных обратных вызовов, связанных с обещаниями. 1, 2, 3

Sync - а, б