Javascript를 비동기적으로 동작하게 해보자
JS 어플리케이션은 단일 스레드에서 동작한다
때문에 멀티 쓰레드에서 발생하는 여러가지 문제(ex 동기화)들에 대하여 걱정할 필요가 없지만, 다양한 동작을 병행하기에 어려움이 있다
따라서 JS에서 여러 동작을 함께 수행하기 위해선 비동기적 테크닉을 사용해야만 한다
여기서 비동기적이란것은 코드의 흐름에서 벗어나 동작하는 것을 말한다
JS의 비동기적 프로그래밍에는 세 가지 패러다임이 있는데, 순서대로 Callback, Promise, Generator 이다
여기서 마지막에 등장한 Generator가 앞의 두 방식보다 좋지만 결국 JS의 비동기적 프로그래밍은 콜백에서 시작하기 때문에 앞의 두 방식도 알아두어야 한다
(이 글에선 제너레이터는 다루지 않는다)
Callback은 말 그대로 call. back. 뒤에 부른다는 의미이다
setTimeout 함수를 보면 확실하게 알 수 있다
setTimeout(fucntion, ms)
에서 첫 번째 인자는 ms만큼 기다린 후에 실행된다
여기서 첫 번째 인자로 들어오는 함수가 '콜백함수'인 것이다
앞에서 말한 제너레이터는 특수한 콜백이나 프라미스와 함께 사용되어야 하고 프라미스는 콜백을 사용해야하기 때문에 비동기적 프로그래밍을 함에 있어서 콜백은 베이스라고 할 수 있다
하지만 콜백만으로 복잡한 비동기적 코드를 작성하기엔 쉽지않다 (ex 콜백 헬)
때문에 나온 것이 프라미스이다
콜백의 단점을 해결하기 위해 만들어졌으며 콜백을 예측 가능한 패턴으로 만들어주며 버그도 상당히 해결해준다
또한 프라미스는 객체이기 때문에 원한다면 어디든 전달 할 수 있다
프라미스 기반 함수는 호출시 프라미스 인스턴스를 반환하고 성공, 실패 둘 중 하나만 발생하며 세 가지의 상태를 가진다
프라미스는 new Promise(콜백함수)
형태로 생성하며 콜백함수는
callback function(resolve, reject)
형태를 가진다
콜백함수의 파라메터resolve
에는 이행(성공)시, reject
에는 거부(실패)시 실행할 작업을 넣어준다
Promise.then(resolveFunc, rejectFunc)
메서드는 프라미스를 반환하고 두 개의 콜백 함수를 인수로 받는다
콜백 함수를 두개 받는 이유는 하나는 프라미스가 이행(성공) 했을 시 나머지 하나는 거부(실패) 했을 시를 위한 콜백 함수이기 때문이다
const promise1 = new Promise((resolve, reject) => {
resolve('Success!');
});
promise1.then((value) => {
console.log(value);
// expected output: "Success!"
});
ECMAScript 2017에 추가된 기능으로 프라미스를 좀 더 읽기 쉽도록 바꿔준다
해당 기능을 사용하기 위해선 해당 함수 앞에 async를 붙여 async 함수로 만들어 준다
// 기본
async function hello() { return "Hello" };
// async 표현식
let hello = async function() { return "Hello" };
// arrow
let hello = async () => { return "Hello" };
await은 async 함수 내에서만 사용이 가능하며 프라미스를 기다리기 위해 사용된다
await 문은 프라미스가 이행되거나 reject 될 때까지 async 함수의 실행을 일시 정지하고 프라미스가 성공되면 일시 정지한 부분부터 다시 실행한다
이 때 await 문의 반환값은 프라미스에서 성공된 값이며, 만약 reject되면 값을 throw한다
참고