비동기적인 처리란 어떤 하나의 처리를 하는 과정중에 다른 처리도 동시에 진행할 수 있는 것을 의미한다. 그림으로 예시를 들면 아래와 같다
위와 같이 비동기적으로 처리를 하게 되면 각각의 작업이 독립적으로 실행되기 때문에 다른 하나의 작업이 막혀서 다른 작업을 못하는 동기 적인 문제가 사라진다. 그러나 아래와 같은 문제가 생긴다
제목과 같이 어느정도 순서를 가지고 비동기적인 작업을 수행해야 할 때 비동기적으로 callback을 이용해서 작성하게 되면 아래와같은 콜백안에서 콜백을 부르고 이러한 과정이 반복되게 된다.
위와 같이 프로그램을 작성하게 되면 가독성이 떨어져서 유지보수가 힘들어진다 이런한 문제를 해결해 주는 것이 promise이다
promise는 비동기 연산이 종료된 이후의 결과값이나 실패 이유를 처리하기 위한 처리기( then ) 를 연결할 수 있도록 해준다 promise를 이용하면 비동기적 메소드를 동기적 메소드 처럼 사용이 가능하다.
이행되거나 거부되지 않은 초기 상태이다 new Promise를 이용하여 프로미스를 생성하면 적용되는 상태이다
프로미스의 연산이 성공적으로 완료되었을 때를 의미한다
프로미스의 연산이 실패했을 경우
프로미스의 이행,거부의 상태를 then, catch메서드가 받아서 처리가 가능하다 then은 보통 이행상태의 프로미스의 결과를 catch는 거부상태의 프로미스의 결과를 받는다. then과 catch는 프로미스를 다시 반환하기 때문에 연결이 가능하다.
let myFirstPromise = new Promise((resolve, reject) => {
setTimeout(function(){
resolve("Success!");
}, 250);
});
myFirstPromise.then((successMessage) => {
console.log("Yay! " + successMessage);
});
async 키워드는 함수앞에 붙여서 사용이 가능하다 async가 붙은 함수는 암시적으로 promise를 사용하여 결과를 반환한다. await키워드는 비동기 함수를 async 함수 안에서 실행 할 때 앞에 붙여 사용할 수 있다 await가 붙은 채로 실행된 비동기 함수는 동기적인 함수처럼 비동기 함수의 실행이 끝날 때 까지 기다렸다가 코드가 실행된다.
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
resolve('resolved');
}, 2000);
});
}
async function asyncCall() {
console.log('calling');
const result = await resolveAfter2Seconds();
console.log(result);
console.log('end');
}
//calling
//resolved
//end 출력된다.
asyncCall();
병렬적으로 프로미스를 실행하면 await의 경우 순서에 맞게 실행하지만 promise의 then은 동시에 실행한다
var resolveAfter2Seconds = function() {
console.log("starting slow promise");
return new Promise(resolve => {
setTimeout(function() {
resolve(20);
console.log("slow promise is done");
}, 2000);
});
};
var resolveAfter1Second = function() {
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==');
const slow = await resolveAfter2Seconds();
console.log(slow);
const fast = await resolveAfter1Second();
console.log(fast);
}
var parallel = function() {
console.log('==PARALLEL with Promise.then==');
resolveAfter2Seconds().then((message)=>console.log(message));
resolveAfter1Second().then((message)=>console.log(message));
}
sequentialStart(); // 3초가 걸린다
setTimeout(parallel, 3000); //2초가 걸린다
위와 같은 결과가 나온다 그러나 await의 경우도 아래와 같이 사용하면 2초가 걸리게 된다.
var concurrentStart = async function() {
console.log('==CONCURRENT START with await==');
const slow = resolveAfter2Seconds(); // starts timer immediately
const fast = resolveAfter1Second();
console.log(await slow);
console.log(await fast); // waits for slow to finish, even though fast is already done!
}
참조 문서
mdn promise
mdn async