Promise가 실행되는 시점

in #promise4 years ago

비동기로 처리해야 할 상황은 서버에서도 그렇고 프론트에서도 그렇고 상당히 많습니다.
그리고 async과 await가 나왔음에도 불구하고 비동기함수 안에서 다른 함수 스코드를 생성하고 그 스코프 내부에서 비동기로 값을 전달해주기 위해서는 Promise를 사용해야 합니다.

function sleep(delay){
  return new Promise((res, rej) => {
     setTimeout(() => {
           //async라면 return을 사용해야 하지만, 
           //현재 스코프에서는 return을 사용해도 비동기의 결과값으로 돌려줄 수 없습니다.
           res();
     }, delay)
  });
}

하지만 Promise를 잘 못 사용하는 경우 알 수 없는 오류를 접하는 경우가 종종 있습니다.

async function execute(){
    let excuteTimes  = [3000, 3000, 3000]; //3초가 걸리는 잡이 3개가 있습니다. 
    
    excuteTimes = excuteTimes.map(sleep);
    console.log(excuteTimes);
    for(let i=0;i<excuteTimes.length;i++){
        await excuteTimes[i]; // 1개의 잡이 끝나고 반복문이 1증가하면서 다음잡이 실행될것 같습니다.
    }
    
    return;
}

execute().then(_ => {
    console.log("몇초나 걸렸죠?");
})

Promise에 대해 잘 알지 못하면 9초 정도 걸리지 않을까 예상할 수 있습니다.
하지만 실제로 실행해보면 결과는 3초 정도 밖에 걸리지 않습니다.

왜 이런 현상이 발생하냐면 Promise는 Promise 인스턴스가 만들어 질 때 프라미스에게 넘겨준 함수를 실행합니다.
그 다음에 내부 함수가 전부다 실행이 되고 비동기 동작이 실행이 완료된 후 결과값을 res로 저장을 하게 됩니다. 그런다음에 저장된 결과값을 then으로 꺼내서 사용하기 때문에 눈으로는 then을 했을 때 실행이 되는거처럼 보일 수 있습니다.

그러면 어떻게 3개의 일을 직렬적으로 처리할 수 있을지 고민을 해봐야 합니다.

Promise가 만들어질 때 넘겨준 함수가 실행이 된다 라는 것을 이해하면 생각보다 간단하다는 걸 알 수 있습니다.

async function execute(){
    let excuteTimes  = [3000, 3000, 3000]; //3초가 걸리는 잡이 3개가 있습니다. 
    
    for(let i=0;i<excuteTimes.length;i++){
        await sleep(excuteTimes[i]); //Promise를 만들고 만들어진 Promise가 작업을 다 끝낼때 까지 기다립니다.
    }
    
    return;
}

execute().then(_ => {
    console.log("몇초나 걸렸죠?");
})

생각보다 더 간단하고 코드도 간결해 졌습니다.

Promise를 병렬로 처리 하기 위해서 map을 사용해 Promise array로 만들고 Promise array를 Promise all로 실행을 하는 경우가 종종 있는데 직렬로 처리를 하게 될시 잘못된 이해는 버그로 만들어질 수 있으니 주의 하시면 좋을것 같습니다.

Coin Marketplace

STEEM 0.28
TRX 0.07
JST 0.042
BTC 30605.20
ETH 2086.77
USDT 1.00
SBD 2.62