>  기사  >  웹 프론트엔드  >  js 함수 실행 과정을 보기 위해 setTimeout을 설명하는 예

js 함수 실행 과정을 보기 위해 setTimeout을 설명하는 예

小云云
小云云원래의
2017-12-20 09:27:121976검색

setTimeout 메서드는 지정된 밀리초 후에 함수나 계산된 표현식을 호출하는 데 사용됩니다. 이 글은 주로 setTimeout의 js 함수 실행 과정을 소개하는데, 필요한 친구들이 참고하면 도움이 될 것 같습니다.


for (var i = 0; i < 5; i++) {
      setTimeout(function () {
        console.log(i)
      }, i * 1000);
    }
    console.log(i);

뭐? 이것은 오래전에 5를 인쇄한 다음 5를 인쇄하고 6개의 5가 인쇄될 때까지 매초마다 5를 인쇄하는 구현 방법이 아닌가? 그렇다면 질문이 생깁니다. 0,1,2,3,4,5를 순서대로 인쇄하려면 어떻게 해야 합니까? 사실 이전에는 두 가지 방법이 있다는 것을 알고 있었습니다. 하나는 다음과 같습니다.


function log(i){
setTimeout(function(){
console.log(i)
},i*1000)
};
for (var i = 0; i < 5; i++) {
      log(i) ;
    }
    console.log(i);

또 하나는 이렇습니다.


for(var i=0;i<5;i++){
(function(e){
setTimeout(function(){
console.log(e)
},i*1000);
})(i);
};
console.log(i);

농담을 두려워하지 마세요. 이전에는 이 두 기능이 실제로 어떤 용도로 사용되었는지 이해하지 못했기 때문에 억지로 기억하고 이렇게 수정했습니다. . 하지만 지금은 강박 장애가 있습니다! 그래서 천천히 분석해 보니 위의 코드는 다음과 같이 구분할 수 있습니다. 조건이 충족될 때

setTimeout(function(){
console.log(i)
},0*1000);

i=1;

setTimeout(function(){
console.log(i)
},1*1000);

i 조건이 충족된 경우


setTimeout(function(){
console.log(i)
},2*1000);

i=3; 조건이 충족된 경우


setTimeout(function(){
console.log(i)
},3*1000);

i=5, 조건이 충족되지 않습니다. 루프에서 빠져나온 다음 for 루프 후에 console.log(i)를 실행하고 마지막으로 5를 인쇄하고 매초마다 5를 인쇄합니다.


정말 흥미롭습니다. setTimeout 내부의 .log는 for 루프 외부의 console.log 후에 실행됩니다. 모직 천? => "queue"라는 단어를 깨닫기 전까지 대기열은 매크로 작업 대기열(Macro Task)과 마이크로 작업 대기열(Micro Task)로 구분됩니다. javascript:

macro-task에는 script(전체 코드) , setTimeout, setInterval이 포함됩니다. , setImmediate, I/O, UI 렌더링.

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

위 함수의 setTimeout이 매크로 작업입니다.

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

이것이 setTimeout 내부의 console.log가 for 루프 외부의 console.log 이후에 실행되는 이유입니다. 함수 실행 컨텍스트에서 seiTimeout 함수는 매크로 작업을 처리하기 위해 대기열에 배치되므로 루프는 setTimeout의 함수는 실행되지 않지만 큐의 함수가 실행되기 전에 모든 전체 코드(큐가 아닌) 실행이 완료될 때까지 기다립니다. 이를 작성하는 것은 약간 혼란스러울 수 있습니다. 사실 저도 약간 혼란스럽습니다. , 하하하! !

더 깊은 이해를 위해 Promise를 추가해 볼 수도 있습니다.

setTimeout(function(){
console.log(i)
},4*1000);

설명 =>

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

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

3. 스크립트 작업 소스의 코드는 실행 중에 Promise 인스턴스를 발견합니다. Promise 생성자의 첫 번째 매개변수는 현재 작업을 직접 실행하면 대기열에 넣지 않으므로 이때는 1이 출력됩니다.

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

5. 그런 다음 실행하면 코드가 then 메서드를 만나고 해당 콜백 함수가 마이크로 태스크로 스택에 푸시되어 Promise의 작업 대기열에 들어갑니다. 이때 Promise의 함수 콜백 함수도 비슷합니다. 즉, 함수 컨텍스트, 즉 스크립트의 대기열이 아닌 모든 코드가 실행되고 마이크로 작업 대기열이 처리될 때까지 해당 작업 대기열에 배치됩니다. 매크로 작업 대기열 이전에

전체 순서는 다음과 같습니다: 컨텍스트 비 대기열 코드 > 마이크로 작업 대기열 콜백 함수 코드 > 매크로 작업 대기열 콜백 함수 코드

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

7. 3을 출력한 후 첫 번째 매크로태스크 스크립트의 코드가 실행됩니다. 이때 대기열에 있는 모든 마이크로태스크가 실행되기 시작합니다. then의 콜백 함수가 스택에 푸시된 후 팝아웃됩니다. 이때 5

8이 출력됩니다. 이때 모든 마이크로 작업이 완료되고 첫 번째 사이클이 종료됩니다. 두 번째 루프는 setTimeout의 작업 대기열에서 시작됩니다. setTimeout의 콜백 함수가 스택에 푸시된 후 이때 4가 출력됩니다.

마지막으로 이해를 돕기 위해 또 다른 코드가 있습니다.

console.log(&#39;golb1&#39;);
setTimeout(function() {
  console.log(&#39;timeout1&#39;);
  new Promise(function(resolve) {
    console.log(&#39;timeout1_promise&#39;);
    resolve();
    setTimeout(function(){
      console.log(&#39;time_timeout&#39;)
    });  
  }).then(function() {
    console.log(&#39;timeout1_then&#39;)
  })
  setTimeout(function() {
   console.log(&#39;timeout1_timeout1&#39;);
  });
})
new Promise(function(resolve) {
  console.log(&#39;glob1_promise&#39;);
  resolve();
  setTimeout(function(){
     console.log(&#39;prp_timeout&#39;)
    });
}).then(function() { console.log(&#39;glob1_then&#39;) })

如果你的执行结果是:golb1=>glob1_promise=>glob1_then=>timeout1=>timeout1_promise=>timeout1_then=>prp_timeout=>time_timeout=>timeout1_timeout1,

可能异步队列算是入门了吧!~~上面的代码看起来有点杂乱,可能用asyns搭配await改造一下会更好,但是这或多或少是鄙人从setTimeout中得到的见解吧

相关推荐:

JavaScript中setTimeout()的使用详解

js中的setTimeout()函数

JavaScript如何使用setTimeout来实现轮循动画的实例详解

위 내용은 js 함수 실행 과정을 보기 위해 setTimeout을 설명하는 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

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