>  기사  >  웹 프론트엔드  >  JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

韦小宝
韦小宝원래의
2018-03-07 15:26:321772검색

JavaScript의 이벤트 루프 메커니즘에 대해 계속 이야기하겠습니다. JavaScript 이벤트 루프 메커니즘에 대한 첫 번째 강의는 아직 끝나지 않았습니다. JavaScript 이벤트 루프 메커니즘에 대해 계속해서 이야기해 보겠습니다.

지난 기사에서 JavaScript 이벤트 루프 메커니즘에 대한 일반적인 소개를 했지만 결국에는 코드 조각과 몇 가지 질문이 남았습니다.

먼저 이 코드부터 시작하겠습니다

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

이 코드에서 setTimeout과 Promise는 모두 작업 소스라고 하며, 서로 다른 작업 소스의

콜백 함수는 서로 다른 작업 대기열에 배치됩니다.

setTimeout의 콜백 함수는 setTimeout의 작업 대기열에 배치됩니다. Promise의 경우 콜백 함수는 전달된 실행자 함수가 아니라 Promise의 작업 대기열에 배치되는 비동기식으로 실행되는 then 메서드의 매개변수입니다. 즉, Promise의 첫 번째 매개변수는 Promise 작업 대기열에 포함되지 않고 현재 대기열에서 실행됩니다.

setTimeout과 Promise의 작업 대기열을 매크로 작업(macro task)이라고 합니다. 물론 우리가 생각하는 것처럼 마이크로 작업(micro task)도 있습니다.

  1. 매크로 작업에는 스크립트(전체 코드), setTimeout, setInterval, setImmediate, I/O, UI 렌더링이 포함됩니다.

  2. 마이크로 작업에는 process.nextTick, Promises, Object.observe, MutationObserver

위의 setImmediate 및 process.nextTick이 Node.JS의 API이며 브라우저에서는 사용할 수 없습니다. 다음은 예입니다. 구현 방법에 대해 걱정하지 마십시오.

이벤트 루프의 순서는 스크립트에서 첫 번째 루프를 시작한 다음 전역 컨텍스트가 함수 호출 스택에 들어가는 것입니다. 매크로 작업이 발생하면 이를 처리하는 모듈로 전달됩니다. 콜백 함수는 매크로 작업 대기열에 배치됩니다. 그 중 마이크로 작업이 발생하면 해당 콜백 함수도 마이크로 작업 대기열에 배치됩니다. 함수 호출 스택이 지워지고 전역 실행 컨텍스트만 남을 때까지 모든 마이크로 작업이 실행되기 시작합니다. 실행 가능한 모든 마이크로 작업이 실행된 후. 루프는 다시 매크로 태스크의 태스크 큐를 실행하고, 실행 후 마이크로 태스크를 모두 실행하는 방식으로 루프가 계속됩니다.

실행 프로세스 분석

다음 분석 아이디어는 이전에 동급생 Bo가 작성한 이벤트 루프 메커니즘에 대한 심층적인 핵심 및 자세한 설명에 따라 분석됩니다.

이전의 밤나무를 분석 대상으로 사용하여 이벤트 루프 메커니즘이 코드를 실행하는 방식을 분석합니다

(function test() {
    setTimeout(function() {console.log(4)}, 0);
    new Promise(function executor(resolve) {
        console.log(1);
        for( var i=0 ; i<10000 ; i++ ) {
            i == 9999 && resolve();
        }
        console.log(2);
    }).then(function() {
        console.log(5);
    });
    console.log(3);
})()

아래 모든 그림의 setTimeout 태스크 팀과 최종 함수 호출 스택은 setTimeout 콜백 함수를 저장합니다. 전체 세트Timeout

timer.

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

1. 먼저 스크립트 태스크 소스가 먼저 실행되고 전역 컨텍스트가 스택에 푸시됩니다.

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

2. 스크립트 작업 소스 코드가 실행 중에 setTimeout을 만나면 매크로 작업으로 콜백 함수를 자체 대기열에 넣습니다.

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

3. 스크립트 작업 소스의 코드가 실행 중에 Promise 인스턴스를 발견합니다. Promise

constructor의 첫 번째 매개변수는 현재 작업이 직접 실행될 때 대기열에 들어가지 않으므로 이때 1이 출력된다는 것입니다.

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

4.

for 루프에서 해결 함수를 만나면 해당 함수가 스택에 푸시된 후 팝업됩니다. 이때 Promise 상태는 Fulfilled가 됩니다. 그런 다음 코드가 실행되어 console.log(2)를 발견하고 2를 출력합니다.

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

5. 그런 다음 실행하면 코드가 then 메서드를 만나고 해당 콜백 함수가 마이크로 작업으로 스택에 푸시되고 Promise 작업 대기열에 들어갑니다.

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

6. 그러면 코드가 실행됩니다. 이때 console.log(3)이 발생하고 3이 출력됩니다.

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

7.输出3之后第一个宏任务script的代码执行完毕,这时候开始开始执行所有在队列之中的micro-task。then的回调函数入栈执行完毕之后出栈,这时候输出5

JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2

8.这时候所有的micro-task执行完毕,第一轮循环结束。第二轮循环从setTimeout的任务队列开始,setTimeout的回调函数入栈执行完毕之后出栈,此时输出4。

总结

总的来说就是:

1、不同的任务会放进不同的任务队列之中。

2、先执行macro-task,等到函数调用栈清空之后再执行所有在队列之中的micro-task。

3、等到所有micro-task执行完之后再从macro-task中的一个任务队列开始执行,就这样一直循环。

4、当有多个macro-task(micro-task)队列时,事件循环的顺序是按上文macro-task(micro-task)的分类中书写的顺序执行的。

测试

说到这里,我们应该都明白了,下面是一个复杂的代码段(改自深入核心,详解事件循环机制),里面有混杂着的micro-task和macro-task,自己画图试试流程哇,然后再用node执行看看输出的顺序是否一致。

console.log(&#39;golb1&#39;);
setImmediate(function() {
    console.log(&#39;immediate1&#39;);
    process.nextTick(function() {
        console.log(&#39;immediate1_nextTick&#39;);
    })
    new Promise(function(resolve) {
        console.log(&#39;immediate1_promise&#39;);
        resolve();
    }).then(function() {
        console.log(&#39;immediate1_then&#39;)
    })
})
setTimeout(function() {
    console.log(&#39;timeout1&#39;);
    process.nextTick(function() {
        console.log(&#39;timeout1_nextTick&#39;);
    })
    new Promise(function(resolve) {
        console.log(&#39;timeout1_promise&#39;);
        resolve();
    }).then(function() {
        console.log(&#39;timeout1_then&#39;)
    })
    setTimeout(function() {
    	console.log(&#39;timeout1_timeout1&#39;);
    process.nextTick(function() {
        console.log(&#39;timeout1_timeout1_nextTick&#39;);
    })
    setImmediate(function() {
    	console.log(&#39;timeout1_setImmediate1&#39;);
    })
    });
})
new Promise(function(resolve) {
    console.log(&#39;glob1_promise&#39;);
    resolve();
}).then(function() {
    console.log(&#39;glob1_then&#39;)
})
process.nextTick(function() {
    console.log(&#39;glob1_nextTick&#39;);
})

讲到这里我们的细说JavaScript事件循环机制也就正式讲完了,看不懂了两篇结合起来看看,练练即可!

先看看我吧:

细说JavaScript事件循环机制-第一讲

위 내용은 JavaScript 이벤트 루프 메커니즘에 대한 자세한 설명 - 강의 2의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.