비동기 작업을 동기적으로 순차대로 실행을 시켜야 할 때가 존재합니다.
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('시간');
});