비동기 작업을 순차대로 실행시키기

맨날·2021년 7월 2일
0

비동기 작업을 동기적으로 순차대로 실행을 시켜야 할 때가 존재합니다.

Promise.all 을 이용하면 배열에 담긴 비동기 작업을 배열의 순서대로 실행은 시켜주지만, 실행의 완료를 기다려 주지는 않습니다.

const list = [1, 2, 3, 4, 5];

function sleep(value) {
  return new Promise(resolve => {
    console.log(`실행순서 : ${value}`);
    setTimeout(() => {
      console.log(`결과 : ${value}`);
      resolve();
    }, (list.length - value) * 500);
  });
}

console.time('시간');

Promise.all(
  list.map((item) => sleep(item))
).then(() => {
  console.timeEnd('시간');
});

위의 코드를 실행해보면 아래와 같은 결과가 나옵니다. 우리가 원하는 것은 하나의 작업이 완료가 되면 그 다음 작업이 실행 되는 것을 원하는 것이기 때문에 promise.all 은 이에 맞지 않습니다.

실행순서 : 1
실행순서 : 2
실행순서 : 3
실행순서 : 4
실행순서 : 5
결과 : 5
결과 : 4
결과 : 3
결과 : 2
결과 : 1

비동기 작업의 완료가 된 후에 다시 비동기 작업을 처리할 때는 then을 사용하면 됩니다.

sleep(list[0])
  .then(() => {
  	return sleep(list[1]);
  })
  .then(() => {
  	return sleep(list[2]);
  })
  .then(() => {
    return sleep(list[3]);
  })
  .then(() => {
    return sleep(list[4]);
  })

위 코드를 실행하면 원하던 대로 앞의 비동기 작업이 완료가 된 후에 다음 비동기 작업을 실행하게 됩니다.

위의 코드를 reduce를 사용하면 좀 더 간결하게 코드를 작성할 수 있습니다.

const list = [1, 2, 3, 4, 5];

function sleep(value) {
  return new Promise(resolve => {
    setTimeout(() => {
      console.log(value);
      resolve();
    }, (list.length - value) * 500);
  });
}

console.time('시간');

list.reduce((promise, item) => {
  return promise.then(() => sleep(item));
}, Promise.resolve())
.then(() => {
  console.timeEnd('시간');
});

0개의 댓글