2016-11-30 8 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 

나는 약속이 비동기 알고 있지만에서는 setTimeout (..) 비동기 작업의 콜백은 약속의 비동기 작업 후 항상. 왜?

+0

약속의 비동기 -는 그 때는이 비동기 적으로 호출되는 등의 경우에도 인라인 동기 찾고 코드 - 그 약속 –

답변

5

"b"뒤에 "1"이 나오는 이유는 무엇입니까?

약속하는대로 .then() 핸들러는 모두 현재 JS 스레드가 완료된 후 비동기 적으로 호출됩니다. 따라서 과 b은 모두 .then() 핸들러보다 먼저 실행되므로 1은 항상 ab 이후가됩니다.

일부 흥미로운 읽기 : T asks, microtasks, queues and schedulesWhat is the order of execution in javascript promisesWriting 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 - OP가 요청한 것보다 약간 다른 질문입니다. 나는 그것들이 스펙에 의한 것인지 아니면 구현 자별인지에 대한 연구를 수행해야 할 것이다.'.then()'핸들러가'queued' 이벤트와'setTimeout()'이벤트를 비교하는 방법에 기반한다. – jfriend00

3

HTML의 경우 동일한 도메인의 페이지 또는 페이지 집합에 대한 event looptask queues을 여러 개 가질 수 있습니다. 동일한 task source의 작업은 브라우저가 다음에 사용할 작업 대기열을 선택하여 항상 동일한 대기열로 이동합니다.

타이머 콜백을 실행하는 작업은 timer task source에서 나와 같은 대기열에 있습니다. 이 대기열을 작업 대기열 "A"이라고합시다.

ECMAscript 2015 (ES6) 사양에는 Promise 반응 콜백을 실행하여 "PromiseJobs"이라는 자체 작업 대기열을 실행하는 작업이 필요합니다. ECMAscript와 HTML 사양은 동일한 언어를 사용하지 않으므로 ECMA의 "약속 작업 대기열"을 HTML 작업 대기열 "B"과 똑같이 생각해 봅시다. 적어도 타이머와 다른 대기열을 사용하십시오.

이론적으로 브라우저는 A 또는 B 대기열에서 작업을 선택하여 실행할 수 있지만 실제로는 약속 대기열 대기열이 우선 순위가 높아지고 타이머 콜백이 실행되기 전에 비워집니다.

"h"가 마지막에 기록되는 이유입니다. Promise then 완료 약속에 대한 호출은 약속 대기열에 작업을 배치합니다. 약속 대기열은 타이머 콜백보다 높은 우선 순위로 실행됩니다. 약속 대기열은 console.log(3)이 실행 된 후에 만 ​​비워져 타이머 호출을 다시 실행할 수 있습니다.


고급

ECMAScript를 보호자는 ECMAScript를 그냥 HTML 브라우저보다 더 많은 환경에서 실행할 수 있기 때문에 자신의 사양에 HTML5 용어 또는 작업 큐의 설명을 사용하지 않도록 선택했다.

약속 대기열의 기본 구현은 별도의 전용 약속 작업 대기열 대신 "미세 작업"대기열을 사용할 수 있습니다. 마이크로 대기열 작업은 현재 스크립트 스레드와 마이크로 대기열에 이전에 추가 된 작업이 완료된 후에 만 ​​실행됩니다.

약속을 이해하는 데 마이크로 작업 대기열에 대한 세부 정보가 필요하지 않습니다.

promise (모든 버전의 IE 등)에 대한 기본 지원이없는 브라우저에 대한 Promise 폴리필은 타이머를 사용할 수 있으며 promise 반응 및 타이머 콜백 순서와 관련하여 기본 구현과 정확히 동일한 방식으로 작동하지 않을 수 있습니다.

0

JS에 익숙하지 않은 사용자에게이 내용을 쉽게 알 수 있습니다.

이 @ getify의 책에서 복사 붙여 넣기입니다

은유를 사용하기 : 이벤트 루프 큐는 탐을 완료하면, 당신은 뒷면에 가야 놀이 공원 타고처럼 줄을 다시 타고. 그러나 작업 대기열은 주행을 끝내는 것과 같지만 줄을 서서 다시 돌아 오는 것과 같습니다.

이벤트 루프 큐 - 약속과 관련된 모든 비동기 콜백 - 약속 시간

작업 대기열에 비해 모든 비동기 콜백 다른합니다. 1, 2, 3

동기화 - A, B