반복문에서의 비동기 함수 실행하기(1) _ 일반 비동기 함수

junamee·2021년 10월 4일
1

자바스크립트

목록 보기
8/11

반복문 내 비동기함수 실행하기

✨ 결과물 : 1초마다 0,1,2,3이 출력되게 만들자 🛠

for(var i =0; i <4; i++){
  setTimeout(()=>{
    console.log(i)
  },1000)
}
// 4(4) 

var가 전역변수로서 위치하고 있다. setTimeout 함수는 비동기 함수로써 1초 뒤 태스크 큐에 담기게 된다. for문을 모두 돌고나서 태스크큐의 작업 내용이 콜스택으로 이동하여 콜백함수(()=>console())를 실행하게 되는데 이 때 필요한 i는 각 실행함수의 컨텍스트에 존재하지 않으며,
i는 스코프 체인을 타고 전역변수 i를 참조하여 약 1초뒤 4를 4번 반환하게 되는 것이다.

01. 즉시실행함수, 클로져

for(var i=0; i<4; i++){
  ((i)=>setTimeout(()=>console.log(i), 1000*i))(i)
}
//0
//1
//2
//3

for문 내부의 함수가 i 값을 인자로 받아 즉시실행함수로 바로 실행되고 setTimeout함수를 반환하는 클로저의 모습을 보여준다. 해당 함수는 태스크큐로 이동하고 for문을 모두 돌아 콜스택이 비워지는 시점에 큐에 저장했던 setTimeout함수를 실행하게 된다.

1초가 지날때 마다 setTimeout함수 내부의 콜백함수를 다시 큐에 담아두게 되고, 다시 한번 콜 스택이 비워지면 큐에서 console.log함수를 실행, 출력하게 된다. 이 때 i값은 클로저의 특성으로 스코프체인을 타고 setTimeout함수에서 i를 찾아본다. 해당 컨텍스트는 i값이 없기 때문에 한 단계 더 상위함수였던 즉시실행함수에서 i값을 참조하게 되어 i를 출력할 수 있게 된다.

02. let 블록스코프

for(let i=0; i<4; i++){
  setTimeout(()=>{
    console.log(i)
  },1000*i)
}

let은 var와 다르게 블록스코프를 갖는다.
(for문 자체를 하나의 블록으로 볼 수 있다.)
때문에 for문 내부의 함수를 실행시킬 때마다 스코프를 생성하게 된다.
1초가 지날 때마다 console.log 콜백함수를 태스크 큐로 이동시키고, 스택이 비워질 때 큐의 콜백함수를 실행하는 시점에서의 i는 각 함수마다 생성되었던 scope의 i를 참조하게 된다.

03. setInterval함수를 적용한 경우

  let i = 0
  let counter = setInterval(()=>{
    console.log(i++)
    if(i>=4) clearInterval(counter)
  },1000)

04. forEach 를 사용한 배열 함수 실행

const funcs = []
for(let i =0; i <4; i++){
    funcs.push(()=>console.log(i))
}

funcs.forEach((func,idx)=>setTimeout(func, 1000*idx))

여기서 let대신 var를 사용하게 되면 i는 4를 가르키게 된다.


profile
아티클리스트 - bit.ly/3wjIlZJ

0개의 댓글