자바스크립트는 싱글 스레드로 한번에 한가지 작업밖에 처리 할 수 없다. 하지만, 브라우저에게 일을 맡기거나 하는 방식으로 비동기처리를 하여 동시성을 가진 프로그램처럼 돌아갈 수 있다.
web API등을 통해 브라우저에서 요청하고 받아오는 방식이 가능하다.
하지만, 자바스크립트 내부에서도 비동기 처리를 할 수 있는 방법이 있다.
let asynchnous = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('5 secs')
}, 5000);
})
asynchnous.then((resp) => {
console.log(`after ${resp}`);
})
// after 5 secs
Promise
클래스를 할당하여 새로운 비동기 처리를 구현할 수 있다.
Promise
객체중 마지막 처리가 완료되면 모든 값을 반환Promise
객체 중 먼저 처리된 값을 반환함Promise
객체를 주어진 값으로 반환함Promise
객체를 주어진 값으로 거절함async
를 키워드로 가진 함수는 await
키워드 앞에서 대기한다.
async function foo() {
await 1
}
// 위 아래는 같은 의미로 볼 수 있다.
function foo() {
return Promise.resolve(1).then(() => undefined)
}
var resolveAfter2Seconds = function() { // 2초 후에 'slow promise is done' 출력
console.log("starting slow promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(20);
console.log("slow promise is done");
}, 2000);
});
};
var resolveAfter1Second = function() { // 1초 후에 'fast promise is done' 출력
console.log("starting fast promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(10);
console.log("fast promise is done");
}, 1000);
});
};
var sequentialStart = async function() {
console.log('==SEQUENTIAL START==');
// If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
const slow = await resolveAfter2Seconds(); // 2초 대기 문구 출력
console.log(slow); // 20
const fast = await resolveAfter1Second(); // 1초 대기 문구 출력
console.log(fast); // 10
}
var concurrentStart = async function() {
console.log('==CONCURRENT START with await==');
const slow = resolveAfter2Seconds(); // starts timer immediately
const fast = resolveAfter1Second();
// 동시에 slow, fast 큐가 시작됨
console.log(await slow); //
console.log(await fast); // waits for slow to finish, even though fast is already done!
}
var stillConcurrent = function() {
console.log('==CONCURRENT START with Promise.all==');
Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then((messages) => {
console.log(messages[0]); // slow
console.log(messages[1]); // fast
});
}
var parallel = function() {
console.log('==PARALLEL with Promise.then==');
resolveAfter2Seconds().then((message)=>console.log(message));
resolveAfter1Second().then((message)=>console.log(message));
}
sequentialStart(); // after 2 seconds, logs "slow", then after 1 more second, "fast"
// wait above to finish
setTimeout(concurrentStart, 4000); // after 2 seconds, logs "slow" and then "fast"
// wait again
setTimeout(stillConcurrent, 7000); // same as concurrentStart
// wait again
setTimeout(parallel, 10000); // trully parallel: after 1 second, logs "fast", then after 1 more second, "slow"
// from MDN Promise
await 와 Promise#then을 혼동하지 마세요
sequentialStart 에서, 첫 번째 await는 2초의 대기 시간을 갖고, 다시 두 번째 await에서 1초의 대기 시간을 갖습니다. 두 번째 타이머는 첫 번째 타이머가 완료될 때 까지 생성되지 않습니다.
concurrentStart 에서, 두 타이머 모두 생성 된 다음 await 합니다. 타이머가 동시에 실행되고 있지만, await 호출은 여전히 연속적 실행중이므로, 두 번째 await 는 첫 번째 호출이 끝날 때 까지 대기합니다. 이렇게하면 3초가 아니라, 가장 느린 타이머에 필요한 2초가 필요합니다. stillConcurrent 에서도 Promise.all 을 사용하여 같은 일이 발생합니다.
두 개 이상의 프러미스를 동시에 wait 하고 싶다면, Promise#then을 사용하여 parallel를 수행할 수 있습니다.