이 글은 캡틴 판교님의 비동기 처리, Promise, async/await 글을 바탕으로 여러 자료들을 합쳐서 작성하였습니다.
만약 우리의 프로그램이 서버로부터 데이터를 요청해서 유저 정보를 보여주는 기능이 있다고 하자. 비동기처리가 없다면, 우리의 프로그램은 서버로부터 데이터를 받을 때까지 멈춰 있을 것이다. 좀 극단적으로 100개의 요청을 한다면, 프로그램은 100개의 요청을 다 받을 때까지 꽤 오랜시간 멈춰있을 것이고, 이는 유저에게 굉장한 불편함을 줄 것이다.
이 외의 다른 예로, 유튜브에서 동기적인 처리를 한다면 동영상이 불러와지는 동안에 유저는 아무것도 할 수가 없다.
비동기 처리는 위와 같은 상황을 해결할 수 있다. 비동기 처리는 특정 로직의 실행이 끝날 떄까지 기다리지 않고 나머지 코드를 먼저 실행하는 것이다.
하지만 비동기 처리에도 문제점이 있다.
아까 예에서 생각해보면,
라고 하였을 때 1번이 완전히 실행되기 전에 3번을 실행하는 것은 전혀 문제가 없고, 원할한 유저 경험을 비동기 처리로 가져올 수 있지만, 1번이 완전히 실행되기 전에 2번을 실행하는 것은 문제를 가져온다. 유저의 데이터를 가져오기 전에 유저 정보를 디스플레이하면 빈 값이 나올 것이다.
콜백함수는 다른 함수에 매개변수로써 전달된 함수를 말한다.
캡틴 판교님의 자바스크립트 비동기 처리와 콜백 함수 포스트에서 콜백함수는 식당 자리 예약에 비유되는데, 이는 매우 적절한 것 같다.
한마디로 말하자면, 주어진 콜백 함수를 데이터가 준비된 순간 그때에 실행하는 것이다.
function getDataFromServer(callback){
setTimeout(function(){
callback();
},10000)
}
function personDetails(){
console.log("PersonDetails are available to use ");
}
getDataFromServer(personDetails); //PersonDetails are available to use
위 코드는 서버로부터 데이터를 받아온 후 주어진 콜백을 실행하는 비동기 처리의 예이다. setTimeout API를 이용하여서 데이터를 받아오는데 걸리는 시간을 구현하였다. 콜백함수를 사용하지 않았다면,
function getDataFromServer(){
setTimeout(function(){
console.log('1');
},1000)
}
function personDetails(){
console.log("PersonDetails are available to use ");
}
getDataFromServer();
personDetails();
personDetails 함수가 먼저 실행되어서 오류가 생겼을 것이다.
결과적으로 personDetails와 같이 어떤 함수의 실행이 끝난 뒤에 실행하고 싶다면, 해당 함수에 콜백함수로 전달해주면 된다.
앞서 언급된 콜백함수를 이용한 비동기 처리 방법은 유용하지만, 여러 콜백이 중첩되었을 때 가시성이 떨어지는 콜백 지옥을 만들기 때문에 복잡한 경우에는 피하는 것이 좋다. 그리하여 나온 것이 바로 Promise이다.
Promise는 비동기 작업이 맞이할 미래의 완료 또는 실패, 그리고 그 결과값을 나타내는 객체이다.
Promise에 관하여 가장 먼저 이해해야 하는 것은 Promise가 가질 수 있는 상태이다.
Pending
아래와 같이 new Promise()가 호출되서 부터 완료되거나 거부되기까지의 상태
new Promise(function(resolve,reject){
//...
});
Fulfilled
콜백함수의 인자인 resolve가 실행된 상태
new Promise(function(resolve, reject) {
resolve();
});
resolve 메서드는 전달받은 값으로 resolved된 Promise 객체를 반환한다. then 메서드를 사용하면 이 전달받은 값을 받을 수 있다.
function getData() {
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('data');
},1000);
});
}
getData().then(value => console.log(value));
new Promise(function(resolve, reject) {
reject();
});
function getData() {
return new Promise(function(resolve,reject){
setTimeout(function(){
reject('data');
},1000);
});
}
getData().catch(error => console.log(error));
async와 await은 비동기 처리를 마치 동기 처리처럼 보여줘서 이해하기 쉽게 만들어주는 키워드이다.
async
async 키워드를 함수 앞에 추가하면, 그 함수는 이제 fulfilled state의 Promise를 반환하게 된다.
async function hello() {
return 'hello';
}
console.log(hello()); // [object Promise] { ... }
고로 올바르게 hello를 출력하기 위해서는 resolve와 함께 쓸 수 있는 then 메서드를 이용할 수 있다.
async function hello() {
return 'hello';
}
hello().then(value=>console.log(value));
// 'hello'
await
await 키워드는 비동기 처리를 하는 Promise 객체를 반환하는 함수(WEB API도 포함) 앞에 사용할 수 있다. await를 해당 함수 앞에 추가하면 그 함수가 반환하는 Promise 객체의 상태가 fulfill state일 때까지 기다리고, 그 결과 값을 반환한다.
오류 핸들링을 위해서는 기존에 사용하는 catch 메서드를 사용해도 되고, try...catch 문을 사용해도 된다.
function hello() {
setTimeout(function(){
console.log('1');
},2000);
}
hello();
console.log('2');
function hello(callback) {
setTimeout(function(){
console.log('1');
callback();
},2000);
}
hello(function(){
console.log('2');
});
function hello() {
return new Promise(function(resolve,reject){
setTimeout(function(){
console.log('1');
resolve('2');
},2000);
});
}
hello().then(data => console.log(data));
async function hello() {
await new Promise(function(resolve,reject){
setTimeout(function(){
console.log('1');
resolve('1');
},2000);
});
console.log('2');
}
hello();
Asynchronous programming
https://joshua1988.github.io/web-development/javascript/javascript-asynchronous-operation/
https://developer.mozilla.org/ko/docs/Learn/JavaScript/Asynchronous/Introducing
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Concepts
Async Callback
https://velog.io/@two_jay/callback-과-비동기-프로그래밍
https://medium.datadriveninvestor.com/understand-callback-function-in-javascript-b2961cdc9bc7
Promise
https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Promise
async & await
https://joshua1988.github.io/web-development/javascript/js-async-await/
https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous/Async_await