setTimeout 에서 js 함수 실행 과정 보기

솔직히 이 글 을 쓸 때 마음 이 좀 답답 하 다.충격 을 받 았 기 때문에 왜?괴 롭 히 는 것 을 좋아해 서 실수 로 이'간단 하 다'는 함 수 를 보 았 다.

for (var i = 0; i < 5; i++) {
      setTimeout(function () {
        console.log(i)
      }, i * 1000);
    }
    console.log(i);
뭐?이것 은 내 가 아주 오래 전에 본 것 이다.먼저 5 개 를 인쇄 하고 5 개 를 인쇄 한 후에 1 초 마다 5 개 를 인쇄 하고 6 개 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);
농담 을 두려워 하지 않 습 니 다.그 전에 저 는 이 두 함수 의 진정한 의미 에서 의 역할 이 무엇 에 쓰 이 는 지 몰 랐 습 니 다.이렇게 기억 하 라 고 강요 하면 됩 니 다.하지만 지금 은 안 됩 니 다.저 는 강박 증 이 있 습 니 다!그래서 나 는 천천히 분석 해 보 았 는데 위의 코드 가 이렇게 분 리 될 수 있다 는 것 을 발견 했다.
i=0 시;조건 만족;

setTimeout(function(){
console.log(i)
},0*1000);
i=1 시;조건 만족;

setTimeout(function(){
console.log(i)
},1*1000);
i=2 시;조건 만족;

setTimeout(function(){
console.log(i)
},2*1000);
i=3 시;조건 만족;

setTimeout(function(){
console.log(i)
},3*1000);
i=4 시;조건 만족;

setTimeout(function(){
console.log(i)
},4*1000);
i=5 시,조건 을 만족 시 키 지 않 고 순환 에서 벗 어 나 for 순환 뒤의 console.log(i)를 실행 하고 5 를 인쇄 합 니 다.마지막 으로 초당 5 인쇄 하기;
재 미 있 네요.왜 setTimeout 에 있 는 console.log 는 for 순환 밖의 console.log 에서 실 행 됩 니까?이 단어=>"대기 열"을 깨 달 을 때 까지 대기 열 에는 매크로 작업 대기 열(Macro Task)과 마이크로 작업 대기 열(Micro Task)의 구분 이 있 습 니 다.자바 script 에서:
macro-task 는 script(전체 코드),setTimeout,setInterval,setImmediate,I/O,UI rendering 을 포함한다.
micro-task 는 process.nextTick,Promises,Object.observe,MutationObserver 를 포함한다.
위 함수 의 setTimeout 은 매크로 작업 에 속 합 니 다.
js 에서 이벤트 순환 의 순 서 는 script 에서 첫 번 째 순환 을 시작 한 다음 에 전체 컨 텍스트 가 함수 호출 스 택 에 들 어 갔 습 니 다.macro-task 를 만나면 이 를 처리 모듈 에 맡 긴 다음 에 리 셋 함 수 를 macro-task 의 대기 열 에 넣 었 습 니 다.micro-task 를 만 나 도 리 셋 함 수 를 micro-task 의 대기 열 에 넣 었 습 니 다.함수 호출 스 택 이 비 워 질 때 까지 전체 컨 텍스트 만 실행 한 다음 모든 micro-task 를 실행 합 니 다.실행 가능 한 모든 micro-task 가 실 행 된 후에macro-task 의 작업 대기 열 을 다시 실행 하고 실행 한 후에 모든 micro-task 를 실행 합 니 다.이렇게 계속 순환 합 니 다.
이것 이 바로 setTimeout 안의 console.log 가 for 순환 밖의 console.log 에서 실행 되 는 이유 입 니 다.함수 실행 컨 텍스트 에서 sei Timeout 함 수 는 그의 macro-task 를 처리 하 는 대기 열 에 들 어가 기 때문에 순환 할 때 setTimeout 안의 function 은 실행 되 지 않 습 니 다.모든 전체 코드(비 대기 열)가 완 료 된 후에 야 대기 열 에 있 는 함 수 를 실행 할 수 있 습 니 다.여기까지 쓰 면 좀 어 리 석 을 수도 있어 요.사실 저도 좀 어 리 석 어 요.하하 하!!
이 해 를 깊이 있 게 하기 위해 Promise 를 넣 어 볼 수도 있 습 니 다.그래서 이것 이 있 습 니 다.

(function copy() {
  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);
})()
해명 하 다
1.우선,script 작업 원본 이 먼저 실행 되 고 전체 컨 텍스트 가 스 택 에 들 어 갑 니 다.
2.script 작업 소스 의 코드 가 실 행 될 때 setTimeout 을 만 났 습 니 다.macro-task 로 서 리 셋 함 수 를 자신의 대기 열 에 넣 습 니 다.
3.script 작업 원본 의 코드 가 실 행 될 때 Promise 인 스 턴 스 를 만 났 습 니 다.Promise 구조 함수 의 첫 번 째 인 자 는 현재 작업 을 직접 수행 하 는 것 이 대기 열 에 들 어가 지 않 기 때문에 이 때 출력 1 입 니 다.
4.for 순환 에서 resolve 함 수 를 만 나 함수 가 스 택 에 들 어가 실행 한 후에 스 택 을 나 갑 니 다.이때 Promise 의 상 태 는 Fulfilled 가 됩 니 다.코드 는 이어서 console.log(2)를 만 나 출력 2 를 실행 합 니 다.
5.이어서 코드 가 then 방법 을 만 났 습 니 다.그 리 셋 함 수 는 micro-task 로 스 택 에 들 어가 Promise 의 작업 대기 열 에 들 어 갑 니 다.이때 Promise 의 then 안의 function 리 셋 함수 와 setTimeout 안의 function 리 셋 함수 가 서로 다른 뜻 을 가지 고 각자 의 작업 대기 열 에 들 어 갑 니 다.
함수 컨 텍스트 즉 script 의 모든 비 대기 열 코드 가 실 행 될 때 까지 실행 합 니 다.또한 마이크로 작업 대기 열 은 매크로 작업 대기 열 보다 우선 합 니 다.
  전체 순 서 는 상하 문 비 대기 열 코드>미 작업 대기 열 리 셋 함수 코드>매크로 작업 대기 열 리 셋 함수 코드
6.코드 를 이어서 실행 합 니 다.이때 console.log(3)를 만 나 3 을 출력 합 니 다.
7.출력 3 후 첫 번 째 매크로 작업 script 의 코드 가 실 행 됩 니 다.이 때 부터 모든 대기 열 에 있 는 micro-task 를 실행 합 니 다.then 의 리 턴 함수 가 스 택 에 들 어가 서 실행 이 끝 난 후에 스 택 을 나 갑 니 다.이때 5 를 출력 합 니 다.
8.이때 모든 micro-task 가 실행 되 고 1 차 순환 이 끝 납 니 다.두 번 째 순환 은 setTimeout 의 작업 대기 열 에서 시작 합 니 다.setTimeout 의 리 셋 함수 가 스 택 에 들 어가 서 실 행 된 후에 스 택 을 나 갑 니 다.이때 4 를 출력 합 니 다.
마지막 으로 이 해 를 깊이 있 게 하기 위해 다음 코드 를 추가 합 니 다.

console.log('golb1');
setTimeout(function() {
  console.log('timeout1');
  new Promise(function(resolve) {
    console.log('timeout1_promise');
    resolve();
    setTimeout(function(){
      console.log('time_timeout')
    });  
  }).then(function() {
    console.log('timeout1_then')
  })
  setTimeout(function() {
   console.log('timeout1_timeout1');
  });
})
new Promise(function(resolve) {
  console.log('glob1_promise');
  resolve();
  setTimeout(function(){
     console.log('prp_timeout')
    });
}).then(function() { console.log('glob1_then') })
만약 당신 의 실행 결과 가:golb 1=>glob 1 이 라면promise=>glob1_then=>timeout1=>timeout1_promise=>timeout1_then=>prp_timeout=>time_timeout=>timeout1_timeout1,
비동기 대열 이 입문 이 었 나 봐 요!~위의 코드 는 좀 복잡 해 보 입 니 다.asyns 와 await 를 조합 하여 개조 하 는 것 이 좋 을 것 같 습 니 다.그러나 이것 은 많 든 적 든 저 는 setTimeout 에서 얻 은 견해 입 니 다.
총결산
위 에서 말 한 것 은 소 편 이 여러분 에 게 소개 한 setTimeout 에서 js 함수 의 집행 과정 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 저 에 게 메 시 지 를 남 겨 주세요.소 편 은 제때에 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

좋은 웹페이지 즐겨찾기