-
Promise, AsyncJavaScript 2022. 1. 10. 16:23
프로미스와 어씽크를 알기 위해선 동기와 비동기 콜백의 개념부터 알아야 한다.
동기코드: 순차적으로 실행 되는 코드. 동기식 처리 모델(Synchronous processing model)은 직렬적으로 태스크(task)를 수행한다. 즉, 태스크는 순차적으로 실행되며 어떤 작업이 수행 중이면 다음 작업은 대기하게 된다.
쉬운버전: 요청과 결과가 동시에 일어남. 결과를 볼 때 까지 기다려야함.
비동기코드: 비동기식 처리 모델(Asynchronous processing model 또는 Non-Blocking processing model)은 병렬적으로 태스크를 수행한다. 즉, 태스크가 종료되지 않은 상태라 하더라도 대기하지 않고 다음 태스크를 실행한다.
쉬운버전: 요청과 결과가 일어나는 것이 시간차가 있음. 결과가 주어지는데 시간이 필요하더라도 그 시간동안 다른작업을 할 수 있음(ex:: setTimeout함수의 설정시간동안 다른 작업을 먼저하는것)
콜백함수: 인자로 함수(callback)를 받아서, 함수내부에서 호출(callback(a+b))한뒤 , 인자로 다시 리턴 해주는 함수
function calValue(a, b){ setTimeout(() => { return a + b; }, 100) } const r = calValue(10, 20) const z = r; //r=undefined 0.1초 이후에 함수가 실행 되므로 명시적 리턴값이 없을땐 js에서 undefined작성 //z도 undefined가 나옴. //이 다음에 setTimeout이 실행되지만 이미 함수가 지나가버렸으므로 return될 곳이 없음
위와 같은 코드가 비동기적 상황. calValue안의 코드와 바깥쪽 코드의 흐름이 맞지가 않음. 이 흐름을 맞게 해주기 위해서 callback을 사용.
function calValue(a, b, callback){ setTimeout(() => { return callback(a + b); }, 100) } const r = calValue(10, 20, (result) => { console.log(result) }); const z = r; //undefined 리턴값은 그대로 0 콜백에서 리턴을 안해줬으므로 //30이 나옴 콘솔값
callback의 경우 콜백안에서 또 콜백이 되면 함수가 굉장히 복잡해진다. 이를 간단하게 해주기 위해서 Promise를 배워보자.
Promise is a javascript object for asynchronous operation.
프로미스는 비동기처리를 위한 객체다.
Promise는 다음과 같이 사용한다
const myPromise = new Promise((resolve, reject) => { resolve();//성공시 호출 then reject();// 실패시 호출 }); myPromise.then(()=>()) // resolve가 호출된 응답으로 then메서드 내의 함수가 실행됨
얼핏 보기에는 promise가 더 복잡해보이지만 밑의 밑의 예제처럼 .then으로 계속 메소드 체이닝을 해줄수가 있기 때문에 여러개의 콜백이 겹치는 경우 함수보다는 then을 통한 가독성 향상이 가능하다.
then 메서드는 두개의 인수를 전달 받을 수 있다.
- 첫번째 콜백 함수는 프로미스가 fulfil상태가 되면 호출 된다. 이 때 콜백함수는 프로미스의 비동기 처리 결과를 전달 받는다.
- 두번째 콜백 함수는 프로미스가 rejected상태가 되면 호출 된다. 이 때 콜백함수는 프로미스의 에러를 인수로 전달 받는다.
then 메서드를 호출하면 언제나 새로운 promise객체가 반환된다.
then메서드의 콜백함수가 promise를 반환하면 그 프로미스를 그대로 반환하고, 콜백함수가 프로미스가 아닌 값을 반환하면 그 값을 암묵적으로 resolve 또는 reject하여 프로미스를 생성하여 반환한다.
function getData() { return new Promise({ // ... }); } // then() 으로 여러 개의 프로미스를 연결한 형식 getData() .then(function(data) { // ... }) .then(function() { // ... }) .then(function() { // ... });
new Promise(function(resolve, reject){ setTimeout(function() { resolve(1); }, 2000); }) .then(function(result) { console.log(result); // 1 return result + 10; }) .then(function(result) { console.log(result); // 11 return result + 20; }) .then(function(result) { console.log(result); // 31 });
실무에서 있을 법한 프로미스 연결 사례
실제 웹 서비스에서 있을 법한 사용자 로그인 인증 로직에 프로미스를 여러 개 연결해보겠습니다.
getData(userInfo) .then(parseValue) .then(auth) .then(diaplay);
위 코드는 페이지에 입력된 사용자 정보를 받아와 파싱, 인증 등의 작업을 거치는 코드를 나타내었습니다. 여기서 userInfo는 사용자 정보가 담긴 객체를 의미하고, parseValue, auth, display는 각각 프로미스를 반환해주는 함수라고 가정했습니다. 아래와 같이 말이죠.
var userInfo = { id: 'test@abc.com', pw: '****' }; function parseValue() { return new Promise({ // ... }); } function auth() { return new Promise({ // ... }); } function display() { return new Promise({ // ... }); }
실패할때는 다음과 같이 구현.
const myPromise = new Promise((resolve, reject) => { setTimeout(() => { reject(new Error()); }, 1000); });
async
async/await 문법은 ES8에 해당하는 문법으로서, Promise 를 더욱 쉽게 사용 할 수 있게 해줍니다.
즉, Promise의 resolve와 reject, .then()를 우리가 익숙한 동기 함수를 작성하는 것처럼 만들어주기 위해 추가된 문법이라 생각하시면 됩니다. 이 과정에서 평상시 사용하던 것 처럼 try{...} catch{...}문을 사용할 수 있는 것이고요. 그렇지만 이렇게 만들어진 async function도 Promise를 반환하므로, Promise를 이용해 만든 함수처럼 사용할 수 있는 것입니다.
함수에서 async 를 사용하면, 해당 함수는 결과값으로 Promise 를 반환하게 됩니다. 따라서 다음과 같이 코드를 작성 할 수 있습니다.
function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } undefined async function process() { console.log('안녕'); await sleep(1000); console.log('하이룽'); }
async는 Promise를 리턴
그리고 Promise 의 앞부분에 await 을 넣어주면 해당 프로미스가 끝날때까지 기다렸다가 다음 작업을 수행 할 수 있습니다.
process().then(() => { console.log('작업이 끝났어요!'); });
결과적으로 promise를 반환하므로 위에 코드에 다음을 추가해서 잘 작동이 된다
참고:
https://learnjs.vlpt.us/async/02-async-await.html
https://joshua1988.github.io/web-development/javascript/js-async-await/
'JavaScript' 카테고리의 다른 글
자바스크립트 함수의 특징 with redux Thunk (0) 2022.03.23 default export, export (0) 2022.01.15 Callback (0) 2022.01.06 Object.keys (0) 2022.01.02 [ES6] Spread syntax (...) (0) 2022.01.02