오늘 배운 것 프로미스 비동기 처리로 발생한은 콜백헬과 에러처리에 대한 어려움으로 ES6에서 프로미스가 등장하였다.
콜백을 사용한 GET 비동기 함수
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 const get = (url, callback ) => { const xhr = new XMLHttpRequest(); xhr.open("GET" , url); xhr.send(); xhr.onload = () => { if (xhr.status === 200 ) { callback(JSON .parse(xhr.response)); } else { console .error(`${xhr.status} ${xhr.statusText} ` ); } }; }; const url = "https://jsonplaceholder.typicode.com" ;get(`${url} /posts/1` , ({ userId } ) => { console .log(userId); get(`${url} /users/${userId} ` , (userInfo ) => { console .log(userInfo); }); });
프로미스와 후속처리 메서드를 사용한 GET 메서드
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 const get = (url, callback ) => { return new Promise ((resolve, reject ) => { const xhr = new XMLHttpRequest(); xhr.open('GET' , url); xhr.send(); xhr.onload = () => { if (xhr.status === 200 ) { resolve(JSON .parse(xhr.response)); } else { reject(new Erro(xhr.status)); } }; }); }; const url = 'https://jsonplaceholder.typicode.com' ;get(`${url} /posts/1` ) .then(({ userId } ) => get(`${url} /users/${userId} ` )); .then(console .log);
후속처리 메서드는 일의 순서 대로 작성하는 것이 가독성이 좋다.
프로미스는 프로미스 객체를 반환하기 때문에 return
값이 프로미스 객체라면 바로 반환이 가능하지만 아니라면 프로미스 객체를 생성하여 값을 설정하고 넘긴다.
위의 경우 console.log
메서드가 중간에서 후속처리를했었다면 명시적으로 반환값을 넘기지 않으면 프로미스에 undefined
값을 설정하고 반환한다.
1 2 3 4 5 6 get(`${url} /posts/1` ) .then((post ) => { console .log(post); return post; }) .then(({ userId } ) => get(`${url} /users/${userId} ` ));
Promise.all 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const requestData1 = () => new Promise ((resolve ) => setTimeout (() => resolve(1 ), 3000 )); const requestData2 = () => new Promise ((resolve ) => setTimeout (() => resolve(2 ), 2000 )); const requestData3 = () => new Promise ((resolve ) => setTimeout (() => resolve(3 ), 1000 )); const res = [];requestData1() .then((data ) => { res.push(data); return requestData2(); }) .then((data ) => { res.push(data); return requestData3(); }) .then((data ) => { res.push(data); console .log(res); }) .catch(console .error);
위는 직렬 처리로 총 6초가 소요된다. 위와 같은 후속처리 체이닝은 위에서 작성한 GET 메서드와 같은 순차적인 처리가 필요할 때 사용하며 순차적인 처리가 필요한 경우가 아니라면 병렬 처리한다.
1 2 3 4 5 6 7 8 9 10 const requestData1 = () => new Promise ((resolve ) => setTimeout (() => resolve(1 ), 3000 )); const requestData2 = () => new Promise ((resolve ) => setTimeout (() => resolve(2 ), 2000 )); const requestData3 = () => new Promise ((resolve ) => setTimeout (() => resolve(3 ), 1000 )); Promise .all([requestData1(), requestData2(), requestData3()]) .then(console .log) .catch(console .error);
위는 병렬 처리 로 동시에 시작하기 때문에 총 3초가 소요된다. 병렬 처리가 훨씬 효율적이기 때문에 Promise.all
을 사용해야한다.
all
메서드는 프로미스 객체로 이루어진 배열(이터러블)객체에 담아서 사용한다. 결과값으로 배열에 각 프로미스 객체의 결과값인 프로미스 객체가 순서대로 담기기 때문에 then
메서드로 받아야한다.
all 메서드에서 하나라도 rejected될 경우 모두 error 처리된다.
1 2 3 4 5 6 7 8 9 10 const githubIds = ["jeresig" , "ahejlsberg" , "ungmo2" ];Promise .all( githubIds.map((id ) => promiseGet(`https://api.github.com/users/${id} ` )) ) .then((users ) => users.map((user ) => user.name)) .then(console .log) .catch(console .error);
all 메서드는 위와 같은 GET으로 여러 값을 받을 때 사용할 수 있다.
Promise.allSettled 1 2 3 4 5 6 7 8 9 10 11 12 Promise .allSettled([ new Promise ((resolve ) => setTimeout (() => resolve(1 ), 2000 )), new Promise ((_, reject ) => setTimeout (() => reject(new Error ("Error!" )), 1000 ) ), ]).then(console .log);
모든 Settled 상태(fulfilled, rejected)를 반환한다.
Nyong’s GitHub