javascript promises

88
JAVASCRIPT PROMISES in ECMAScript6 (Harmony)

Upload: uyeong-ju

Post on 15-Jul-2015

1.808 views

Category:

Technology


3 download

TRANSCRIPT

Page 1: JavaScript Promises

   

JAVASCRIPT PROMISES in

ECMAScript6 (Harmony)

Page 2: JavaScript Promises

01 02 03 04

Promise란 무엇인가?

Promise 사용하기

Promise의 특징

Promise 직접 구현하기

전통적인 콜백 패

턴이 가지고 있는

문제와 Promise 정

의및 사용 방법에

대해서 개괄적으로

살펴본다.

Promise의 정적 메

서드와 인스턴스

메서드 , 그리고

thenable에 관한

개념 등 조금 더 다

양하고 자세한 내

용을 살펴본다.

Promise에 대해

잘 알려져 있지 않

는 중요한 특징 몇

가지를 소개한다.

ES6����������� ������������������   Promises의����������� ������������������  ����������� ������������������  

베이스가����������� ������������������   되는����������� ������������������  ����������� ������������������  

Promise/A+의����������� ������������������  사����������� ������������������  

양을����������� ������������������  직접����������� ������������������  구현해����������� ������������������  

봄 으 로 써����������� ������������������  ����������� ������������������  

Promise에����������� ������������������   대한����������� ������������������  ����������� ������������������  

이해를����������� ������������������  더욱����������� ������������������  높인����������� ������������������  

다.����������� ������������������  

2  

Page 3: JavaScript Promises

전통적인 콜백 패턴의 문제 1

여러운 비동기 예외 처리

3  

try{ setTimeout(function(){ throw new Error('에러가 발생했다.'); }, 1000); }catch(err){ console.error(err); console.log('에러를 복구했다.'); }

Page 4: JavaScript Promises

전통적인 콜백 패턴의 문제 1

여러운 비동기 예외 처리

try{ setTimeout(function(){ throw new Error('에러가 발생했다.'); }, 1000); }catch(err){ console.error(err); console.log('에러를 복구했다.'); }

global

4  

Page 5: JavaScript Promises

전통적인 콜백 패턴의 문제 1

여러운 비동기 예외 처리

try{ setTimeout(function(){ throw new Error('에러가 발생했다.'); }, 1000); }catch(err){ console.error(err); console.log('에러를 복구했다.'); }

global setTimeout() handler 호출

콜백 등록

5  

Page 6: JavaScript Promises

전통적인 콜백 패턴의 문제 1

여러운 비동기 예외 처리

try{ setTimeout(function(){ throw new Error('에러가 발생했다.'); }, 1000); }catch(err){ console.error(err); console.log('에러를 복구했다.'); }

global time event setTimeout() handler 호출

콜백 등록 발화

6  

Page 7: JavaScript Promises

전통적인 콜백 패턴의 문제 1

여러운 비동기 예외 처리

try{ setTimeout(function(){ throw new Error('에러가 발생했다.'); }, 1000); }catch(err){ console.error(err); console.log('에러를 복구했다.'); }

global time event setTimeout() handler 호출

콜백 등록 발화

예외

7  

Page 8: JavaScript Promises

전통적인 콜백 패턴의 문제 1

여러운 비동기 예외 처리

try{ setTimeout(function(){ throw new Error('에러가 발생했다.'); }, 1000); }catch(err){ console.error(err); console.log('에러를 복구했다.'); }

global time event setTimeout() handler 호출

콜백 등록 발화

예외 통지 예외

8  

Page 9: JavaScript Promises

전통적인 콜백 패턴의 문제 2

복수의 비동기 처리

fs.readdir(source, function(err, files){ if(err){ console.log('Error finding files : ' + err); }else{ file.forEach(function(filename, fileIndex){ console.log(filename); gm(source + filename).size(function(err, vlaues){ if(err){ console.log('Error identifying file size : ' + err); }else{ console.log(filename + ' : ' + values); aspect = (values.width / value.height); widths.forEach(function(width, wwidthIndex){ height = Math.round(width /aspect); console.log('resizing ' + filename + 'to ' + height + 'x' + height); this.resize(width, height).write(

destination + 'w' + width + '_' + filename, function(err){ if(err){ console.log('Error writing file : ' + err); } } ); }); } }); }); } })

9  

Page 10: JavaScript Promises

Promise란?

정의

Promise란 비동기 처리 로직을 추상화한 객체와 그것을 조작하는 방식을 말한다.

E 언어에서 처음 고안됐으며 병렬 및 병행 프로그래밍을 위한 일종의 디자인이다.

비동기����������� ������������������  로직����������� ������������������  

전달  

<Promise>  

인터페이스����������� ������������������  

의존  구현  

<액터>  

10  

Page 11: JavaScript Promises

Promise란?

효과

전통적인 콜백 패턴이 가진 단점을 일부 보완한다.

비동기 처리 시점을 명확하게 표현한다.

Promise 객체의 인터페이스를 이용해 다양한 비동기 처리를 패턴화할 수 있다.

복잡하고 불편한 비동기 예외 처리를 손쉽게 다룰 수 있다.

11  

Page 12: JavaScript Promises

Promise란?

명세

초기 작업

ES6 DRAFT

Promises/A+

https://github.com/domenic/promises-unwrapping

https://people.mozilla.org/~jorendorff/es6-draft.html#sec-promise-constructor

Promises/A+����������� ������������������  :����������� ������������������  https://promisesaplus.com/����������� ������������������  

12  

Page 13: JavaScript Promises

Promise란?

사용된 곳

if('serviceWorker' in navigator){ navigator.serviceWorker.register('/sw=text/sw.js', { scope: '/' }).then(function(sw){ // registration worked console.log('Registration succeeded.'); }).catch(function(err){ // registration filed console.log('Registration filed with ' + err); }) }  

function writeArrayToStream(array, writableStream){ array.forEach(chunk = > writableStream.write(chunk)); return writableStream.close(); } writeArrayToStream([1, 2, 3, 4, 5], writableStream) .then(() => console.log('All done!')) .catch(e => console.log('Error with the stream : ' + e));

Service Worker API

Streams API

13  

Page 14: JavaScript Promises

Promise 살펴보기

Promises API

developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

strawman(폐기)����������� ������������������  :����������� ������������������  http://wiki.ecmascript.org/doku.php?id=strawman:promises����������� ������������������  

Constructor

var promise = new Promise(function(resolve, reject){ // 비동기 처리 작성 // 처리가 끝나면 resolve 또는 reject 호출 });   

Instace Method Static Method

Promise.prototype.then(onFulfilled,����������� ������������������  onRejected)����������� ������������������  

Promise.prototype.catch(onRejected)����������� ������������������  

Promise.all()����������� ������������������  

Promise.race()����������� ������������������  

Promise.resolve()����������� ������������������  

Promise.reject()����������� ������������������  

14  

Page 15: JavaScript Promises

Promise 살펴보기

워크플로우

/** * @returns {Promise} */ function asyncFunction(){ return new Promise(function(resolve, reject){ setTimeout(function(){ resolve('Async Hello world!!'); }, 16); }) }   

asyncFunction().then(function(value){ console.log(value); }).catch(function(error){ console.log(error); });   

asyncFunction().then(function(value){ console.log(value); }, function(error){ console.log(error); });   

asyncFunction()은 Promise의 인스턴스를 반환할 뿐이며 비동기 로직은 모두 Promise에 추상화된다. 비동기 처리가 성공했을 때 호출될 콜백은 then(), 실패했을 때 호출될 콜백은 catch()로 등록한다. catch()는 then()을 이용해 대체할 수도 있다.

15  

Page 16: JavaScript Promises

Promise 살펴보기

상태

초기 상태

성공(또는 해결) 상태

실패(또는 거부) 상태

불편 상태

unresolved����������� ������������������  또는����������� ������������������  Pending,����������� ������������������  ����������� ������������������  

성공도����������� ������������������  실패도����������� ������������������  아닌����������� ������������������  초기����������� ������������������  상태����������� ������������������  

has-resolution����������� ������������������  또는����������� ������������������  Fulfilled,����������� ������������������  ����������� ������������������  

성공(resolve)했을����������� ������������������  때의����������� ������������������  상태����������� ������������������  

has-rejection����������� ������������������  또는����������� ������������������  Rejected,����������� ������������������  ����������� ������������������  

실패(reject)했을����������� ������������������  때의����������� ������������������  상태����������� ������������������  

Settled,����������� ������������������  성공����������� ������������������  또는����������� ������������������  실패����������� ������������������  했을����������� ������������������  때의����������� ������������������  상태.����������� ������������������  

Fulfilled

Rejected

Pending

16  

Page 17: JavaScript Promises

Promise 맛보기

객체 생성

1.  new Promise(fn)으로 promise 객체를 생성한다. 2.  fn에는 비동기 처리를 작성한다.

•  처리 결과가 정상이라면 resolve(결과 값)을 호출한다. •  처리 결과가 비정상이라면 reject(error)을 호출한다.

function getJSON(URL){ return new Promise(function(resolve, reject){ var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function(){ if(req.status === 200){ resolve(JSON.parse(req.responseText)); }else{ reject(new Error(req.statusText)); } }; req.onerror = function(){ reject(new Error(req.statusText)); }; req.send(); }) }   

function doSomething(callback){ var value = 42; if(value === 42){ callback(null, value); }else{ callback(new Error('에러'), null); } }  

17  

Page 18: JavaScript Promises

Promise 맛보기

객체 사용

Promise의����������� ������������������  인스턴스����������� ������������������  메서드를����������� ������������������  이용해����������� ������������������  객체의����������� ������������������  상태가����������� ������������������  ����������� ������������������  변화할����������� ������������������  때����������� ������������������  한����������� ������������������  번만����������� ������������������  호출될����������� ������������������  함수를����������� ������������������  등록한다.����������� ������������������  

Pending

18  

Page 19: JavaScript Promises

Promise 맛보기

객체 사용

Promise의����������� ������������������  인스턴스����������� ������������������  메서드를����������� ������������������  이용해����������� ������������������  객체의����������� ������������������  상태가����������� ������������������  ����������� ������������������  변화할����������� ������������������  때����������� ������������������  한����������� ������������������  번만����������� ������������������  호출될����������� ������������������  함수를����������� ������������������  등록한다.����������� ������������������  

resolve()가����������� ������������������  호출����������� ������������������  됐을때,����������� ������������������  객체����������� ������������������  상태가����������� ������������������  Fulfilled����������� ������������������  됐음을����������� ������������������  뜻하며����������� ������������������  onFulfilled가����������� ������������������  호출된다.

onFulfilled

resolve() value

Pending

19  

Page 20: JavaScript Promises

Promise 맛보기

객체 사용

Promise의����������� ������������������  인스턴스����������� ������������������  메서드를����������� ������������������  이용해����������� ������������������  객체의����������� ������������������  상태가����������� ������������������  ����������� ������������������  변화할����������� ������������������  때����������� ������������������  한����������� ������������������  번만����������� ������������������  호출될����������� ������������������  함수를����������� ������������������  등록한다.����������� ������������������  

resolve()가����������� ������������������  호출����������� ������������������  됐을때,����������� ������������������  객체����������� ������������������  상태가����������� ������������������  Fulfilled����������� ������������������  됐음을����������� ������������������  뜻하며����������� ������������������  onFulfilled가����������� ������������������  호출된다.

reject()가����������� ������������������  호출����������� ������������������  됐을때,����������� ������������������  객체����������� ������������������  상태가����������� ������������������  Rejected����������� ������������������  됐음을����������� ������������������  뜻하며����������� ������������������  onRejected가����������� ������������������  호출된다.

onRejected

reject() error

Pending

20  

Page 21: JavaScript Promises

Promise 맛보기

객체 사용

Promise의����������� ������������������  인스턴스����������� ������������������  메서드를����������� ������������������  이용해����������� ������������������  객체의����������� ������������������  상태가����������� ������������������  ����������� ������������������  변화할����������� ������������������  때����������� ������������������  한����������� ������������������  번만����������� ������������������  호출될����������� ������������������  함수를����������� ������������������  등록한다.����������� ������������������  

resolve()가����������� ������������������  호출����������� ������������������  됐을때,����������� ������������������  객체����������� ������������������  상태가����������� ������������������  Fulfilled����������� ������������������  됐음을����������� ������������������  뜻하며����������� ������������������  onFulfilled가����������� ������������������  호출된다.

reject()가����������� ������������������  호출����������� ������������������  됐을때,����������� ������������������  객체����������� ������������������  상태가����������� ������������������  Rejected����������� ������������������  됐음을����������� ������������������  뜻하며����������� ������������������  onRejected가����������� ������������������  호출된다.

onRejected

reject() error

onFulfilled

resolve() value

getJSON('/api/stores').then(function(value){ console.log(value); }).catch(function(error){ console.log(error.message); });   

getJSON(’/api/stores').then(function(value){ console.log(value); }, function(error){ console.log(error.message); });   

Pending

21  

Page 22: JavaScript Promises

   PROMISES 사용하기

Page 23: JavaScript Promises

Promise.resolve

new Promise() 단축 표기

Promise.resolve()를����������� ������������������  사용하면����������� ������������������  new����������� ������������������  Promise()����������� ������������������  구문을����������� ������������������  단축해����������� ������������������  표기할����������� ������������������  수����������� ������������������  있다.����������� ������������������  

23  

Page 24: JavaScript Promises

Promise.resolve

new Promise() 단축 표기

Promise.resolve()를����������� ������������������  사용하면����������� ������������������  new����������� ������������������  Promise()����������� ������������������  구문을����������� ������������������  단축해����������� ������������������  표기할����������� ������������������  수����������� ������������������  있다.����������� ������������������  

var promise = new Promise(function(resolve){ resolve(42); }).then(function(value){ console.log(value); });  

var promise = Promise.resolve(42).then(function(value){ console.log(value); });   

24  

Page 25: JavaScript Promises

Promise.resolve

thenable과 resolve

then()을����������� ������������������  가진����������� ������������������  유사����������� ������������������  promise����������� ������������������  객체를����������� ������������������  thenable한����������� ������������������  객체라고����������� ������������������  한다.����������� ������������������  Promise.resolve()는����������� ������������������  thenable����������� ������������������  객체를����������� ������������������  promise����������� ������������������  객체로����������� ������������������  변환할����������� ������������������  수����������� ������������������  있다.����������� ������������������  (이����������� ������������������  기능은����������� ������������������  과거����������� ������������������  Promise.cast()라는����������� ������������������  별도의����������� ������������������  메서드로����������� ������������������  존재했었다.)����������� ������������������  

25  

Page 26: JavaScript Promises

Promise.resolve

thenable과 resolve

then()을����������� ������������������  가진����������� ������������������  유사����������� ������������������  promise����������� ������������������  객체를����������� ������������������  thenable한����������� ������������������  객체라고����������� ������������������  한다.����������� ������������������  Promise.resolve()는����������� ������������������  thenable����������� ������������������  객체를����������� ������������������  promise����������� ������������������  객체로����������� ������������������  변환하는����������� ������������������  기능이����������� ������������������  있다.����������� ������������������  (이����������� ������������������  기능은����������� ������������������  과거����������� ������������������  Promise.cast()라는����������� ������������������  별도의����������� ������������������  메서드로����������� ������������������  존재했었다.)����������� ������������������  

26  

var promise = Promise.resolve($.ajax('/api/comments')); promise.then(function(value){ console.log(value); }).catch(function(error){ console.log(error.statusText); });   

노트����������� ������������������  :����������� ������������������  jQuery.ajax()가����������� ������������������  반환하는����������� ������������������  jqXHR����������� ������������������  객체는����������� ������������������  Deferred����������� ������������������  Object를����������� ������������������  상속한다.����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  하지만����������� ������������������  Deferred는����������� ������������������  Promise/A+나����������� ������������������  ES6����������� ������������������  Promise����������� ������������������  사양을����������� ������������������  따른����������� ������������������  것이����������� ������������������  아니므로����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  특정����������� ������������������  처리시����������� ������������������  문제가����������� ������������������  발생할����������� ������������������  수����������� ������������������  있다.����������� ������������������  

Page 27: JavaScript Promises

Promise.reject

new Promise() 단축 표기

Promise.reject()를����������� ������������������  사용하면����������� ������������������  new����������� ������������������  Promise()����������� ������������������  구문을����������� ������������������  단축해����������� ������������������  표기할����������� ������������������  수����������� ������������������  있다.����������� ������������������  

27  

var promise = new Promise(function(resolve, reject){ reject(new Error('오류')); }).catch(function(error){ console.log(error.message); });   

Promise.reject(new Error('오류')).catch(function(error){ console.log(error.message); });   

Page 28: JavaScript Promises

Promise.prototype.then

메서드 체인

promise����������� ������������������  객체의����������� ������������������  then()과����������� ������������������  catch()를����������� ������������������  이용해����������� ������������������  메서드를����������� ������������������  체인할����������� ������������������  수����������� ������������������  있다.����������� ������������������  메서드를����������� ������������������  체인하여����������� ������������������  작성한����������� ������������������  콜백����������� ������������������  함수는����������� ������������������  등록한����������� ������������������  순서대로����������� ������������������  처리된다.����������� ������������������  

28  

Page 29: JavaScript Promises

Promise.prototype.then

메서드 체인

promise����������� ������������������  객체의����������� ������������������  then()과����������� ������������������  catch()를����������� ������������������  이용해����������� ������������������  메서드를����������� ������������������  체인할����������� ������������������  수����������� ������������������  있다.����������� ������������������  메서드를����������� ������������������  체인하여����������� ������������������  작성한����������� ������������������  콜백����������� ������������������  함수는����������� ������������������  등록한����������� ������������������  순서대로����������� ������������������  처리된다.����������� ������������������  

29  

function taskA(){ console.log('Task A'); } function taskB(){ console.log('Task B'); } function onRejected(error){ console.log('Catch Error: A or B', error); } function finalTask(){ console.log('Final Task'); } var promise = Promise.resolve(); promise.then(taskA) .then(taskB) .catch(onRejected) .then(finalTask);   

TaskA  

TaskB  

FinalTask  

onRejected  

Page 30: JavaScript Promises

Promise.prototype.then

메서드 체인

만약����������� ������������������  TaskA에서����������� ������������������  에러가����������� ������������������  발생하면����������� ������������������  TaskB는����������� ������������������  실행되지����������� ������������������  ����������� ������������������  않고����������� ������������������  ����������� ������������������  onRejected와����������� ������������������  finalTask����������� ������������������  순으로����������� ������������������  처리된다.����������� ������������������  

30  

function taskA(){ console.log('Task A'); throw new Error('throw Error @ Task A'); } function taskB(){ console.log('Task B'); } function onRejected(error){ console.log('Catch Error: A or B', error); } function finalTask(){ console.log('Final Task'); } var promise = Promise.resolve(); promise.then(taskA) .then(taskB) .catch(onRejected) .then(finalTask);   

TaskA  

TaskB  

FinalTask  

onRejected  

function taskA(){ console.log('Task A'); return Promise.reject(new Error(…)); }   

Page 31: JavaScript Promises

Promise.prototype.then

결과 값 전달

어떤����������� ������������������  onFulfilled의����������� ������������������  반환����������� ������������������  값은����������� ������������������  ����������� ������������������  다음����������� ������������������  onFulfilled에����������� ������������������  인자로����������� ������������������  전달된다.����������� ������������������  

31  

Page 32: JavaScript Promises

Promise.prototype.then

결과 값 전달

어떤����������� ������������������  onFulfilled의����������� ������������������  반환����������� ������������������  값은����������� ������������������  ����������� ������������������  다음����������� ������������������  onFulfilled에����������� ������������������  인자로����������� ������������������  전달된다.����������� ������������������  

32  

function doubleUp(value){ return value * 2; } function increment(value){ return value + 1; } function output(value){ console.log(value); } var promise = Promise.resolve(1); promise.then(increment) .then(doubleUp) .then(output);   

increment  

doubleUp  

output  

1  

2  

4  

Page 33: JavaScript Promises

Promise.prototype.then

결과 값 전달

어떤����������� ������������������  onFulfilled의����������� ������������������  반환����������� ������������������  값은����������� ������������������  ����������� ������������������  다음����������� ������������������  onFulfilled에����������� ������������������  인자로����������� ������������������  전달된다.����������� ������������������  

33  

function doubleUp(value){ return value * 2; } function increment(value){ return value + 1; } function output(value){ console.log(value); } var promise = Promise.resolve(1); promise.then(increment) .then(doubleUp) .then(output);   

increment  

doubleUp  

output  

1  

2  

4  

반환����������� ������������������   값으로는����������� ������������������   숫자,����������� ������������������   문자열,����������� ������������������   객체뿐����������� ������������������   아니라����������� ������������������   Promise도����������� ������������������  

가능하다.����������� ������������������   내부����������� ������������������   적으로는����������� ������������������   Promise.resolve(반환����������� ������������������   값)처럼����������� ������������������  

처리����������� ������������������   되기����������� ������������������   떄문에����������� ������������������   무엇을����������� ������������������   반환하더라도����������� ������������������   최종적으로는����������� ������������������  

새로운����������� ������������������   promise����������� ������������������   객체가����������� ������������������   반환된다.����������� ������������������   즉,����������� ������������������   then()은����������� ������������������   단순히����������� ������������������  

콜백����������� ������������������   함수를����������� ������������������   등록하기만����������� ������������������   하는게����������� ������������������   아니라����������� ������������������   콜백에서����������� ������������������   반환한����������� ������������������  

값을����������� ������������������   기준으로����������� ������������������   새로운����������� ������������������   promise����������� ������������������   객체를����������� ������������������   생성해����������� ������������������   전달하는����������� ������������������  

기능도����������� ������������������  하고����������� ������������������  있다.����������� ������������������  ����������� ������������������  

function increment(value){ return Promise.resolve(value + 1); }   

Page 34: JavaScript Promises

Promise.prototype.then

복수의 비동기 요청 - callback

then을����������� ������������������  이용해����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  요청을����������� ������������������  구현하는����������� ������������������  방법에����������� ������������������  대해����������� ������������������  소개한다.����������� ������������������  먼저����������� ������������������  전통적인����������� ������������������  콜백����������� ������������������  스타일로����������� ������������������  이를����������� ������������������  구현해����������� ������������������  본다.����������� ������������������  

34  

Page 35: JavaScript Promises

Promise.prototype.then

복수의 비동기 요청 - callback

then을����������� ������������������  이용해����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  요청을����������� ������������������  구현하는����������� ������������������  방법에����������� ������������������  대해����������� ������������������  소개한다.����������� ������������������  먼저����������� ������������������  전통적인����������� ������������������  콜백����������� ������������������  스타일로����������� ������������������  이를����������� ������������������  구현해����������� ������������������  본다.����������� ������������������  

35  

function ajax(URL, callback){ var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function(){ if(req.status === 200){ callback(null, req.responseText); }else{ callback( new Error(req.statusText), req.response ); } }; req.onerror = function(){ callback(new Error(req.statusText)); }; req.send(); }     

function jsonify(callback, error, value){ var result; if(error){ callback(error, value); }else{ try{ result = JSON.parse(value); callback(null, result); }catch(err){ callback(err, value); } } }   

계속����������� ������������������  >>����������� ������������������  

Page 36: JavaScript Promises

Promise.prototype.then

복수의 비동기 요청 - callback

then을����������� ������������������  이용해����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  요청을����������� ������������������  구현하는����������� ������������������  방법에����������� ������������������  대해����������� ������������������  소개한다.����������� ������������������  먼저����������� ������������������  전통적인����������� ������������������  콜백����������� ������������������  스타일로����������� ������������������  이를����������� ������������������  구현해����������� ������������������  본다.����������� ������������������  

36  

var request = { cards : function(callback){ return ajax('/api/cards', jsonify.bind(null, callback)); }, insurances : function(callback){ return ajax('/api/insurances', jsonify.bind(null, callback)); } };   

function all(requests, record, callback){ var req; if(requests.length === 0){ return callback(null, record); } req = requests.shift(); req(function(error, value){ if(error){ callback(error, value); }else{ record.push(value); all(requests, record, callback); } }); }   

all([request.cards, request.insurances], [], function(error, value){ if(error){ console.log(error); }else{ console.log(value); } });   

Page 37: JavaScript Promises

Promise.prototype.then

복수의 비동기 요청 - then

전통적인����������� ������������������  콜백����������� ������������������  패턴이����������� ������������������  가지고����������� ������������������  있는����������� ������������������  문제를����������� ������������������  then()으로����������� ������������������  해결해보자.����������� ������������������  (이해를����������� ������������������  돕기����������� ������������������  위해����������� ������������������  then()을����������� ������������������  사용하지만,����������� ������������������  사실����������� ������������������  ����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  처리����������� ������������������  시����������� ������������������  유용한����������� ������������������  Promise.all()과����������� ������������������  Promise.race()가����������� ������������������  있다.)����������� ������������������  

37  

Page 38: JavaScript Promises

Promise.prototype.then

복수의 비동기 요청 - then

전통적인����������� ������������������  콜백����������� ������������������  패턴이����������� ������������������  가지고����������� ������������������  있는����������� ������������������  문제를����������� ������������������  then()으로����������� ������������������  해결해보자.����������� ������������������  (이해를����������� ������������������  돕기����������� ������������������  위해����������� ������������������  then()을����������� ������������������  사용하지만,����������� ������������������  사실����������� ������������������  ����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  처리����������� ������������������  시����������� ������������������  유용한����������� ������������������  Promise.all()과����������� ������������������  Promise.race()가����������� ������������������  있다.)����������� ������������������  

38  

function ajax(URL){ return new Promise(function(resolve, reject){ var req = new XMLHttpRequest(); req.open('GET', URL, true); req.onload = function(){ if(req.status === 200){ resolve(req.responseText); }else{ reject(new Error(req.statusText)); } }; req.onerror = function(){ reject(new Error(req.statusText)); }; req.send(); }) }   

var request = { cards : function(){ return ajax('/api/cards') .then(JSON.parse) }, insurances : function(){ return ajax('/api/insurances') .then(JSON.parse) } };   

Page 39: JavaScript Promises

Promise.prototype.then

복수의 비동기 요청 - then

전통적인����������� ������������������  콜백����������� ������������������  패턴이����������� ������������������  가지고����������� ������������������  있는����������� ������������������  문제를����������� ������������������  then()으로����������� ������������������  해결해보자.����������� ������������������  (이해를����������� ������������������  돕기����������� ������������������  위해����������� ������������������  then()을����������� ������������������  사용하지만,����������� ������������������  사실����������� ������������������  ����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  처리����������� ������������������  시����������� ������������������  유용한����������� ������������������  Promise.all()과����������� ������������������  Promise.race()가����������� ������������������  있다.)����������� ������������������  

39  

function all(){ var record = []; function recording(value){ record.push(value); return record; } return request.cards().then(recording) .then(request.insurances).then(recording); }   

all().then(function(value){ console.log(value); }).catch(function(error){ console.log(error); });   

Page 40: JavaScript Promises

Promise.prototype.catch

IE에서의 문제

전catch()는����������� ������������������  Promise.then(undefined,����������� ������������������  onRejected)를����������� ������������������  랩핑한����������� ������������������  메서드다.����������� ������������������  promise����������� ������������������  객체가����������� ������������������  Rejected����������� ������������������  상태가����������� ������������������  됐을����������� ������������������  때����������� ������������������  호출될����������� ������������������  콜백����������� ������������������  함수를����������� ������������������  등록하기����������� ������������������  위해����������� ������������������  사용한다.����������� ������������������  

40  

위는����������� ������������������  polyfill을����������� ������������������  사용한����������� ������������������  상태에서����������� ������������������  Promise����������� ������������������  동작����������� ������������������  여부를����������� ������������������  테스트한����������� ������������������  ����������� ������������������  

사진이다.����������� ������������������  IE8����������� ������������������  이하����������� ������������������  브라우저에서는����������� ������������������  “식별자를����������� ������������������  찾을����������� ������������������  수����������� ������������������  없습니다”����������� ������������������  

라는����������� ������������������  메시지와����������� ������������������  함께����������� ������������������  Syntac����������� ������������������  Error가����������� ������������������  발생한다.����������� ������������������  

var promise = Promise.reject(new Error('message')); promise.catch(function(error){ console.log(error.message); });   

var promise = Promise.reject(new Error('message')); promise['catch'](function(error){ console.log(error.message); });   

var promise = Promise.reject(new Error('message')); promise.then(undefined, function(error){ console.log(error.message); });   

ECMAScript3에서는����������� ������������������  예약어를����������� ������������������  객체의����������� ������������������  프로퍼티����������� ������������������  명으로����������� ������������������  사용할����������� ������������������  

수����������� ������������������  없다.����������� ������������������  IE8이하����������� ������������������  버전은����������� ������������������  ECMAScript3를����������� ������������������  따를����������� ������������������  브라우저이다.����������� ������������������  

이런����������� ������������������   문제를����������� ������������������   미연에����������� ������������������   방지하고자����������� ������������������   일부����������� ������������������   라이브러리는����������� ������������������   caught,����������� ������������������  

fail����������� ������������������  등과����������� ������������������  같은����������� ������������������  이름으로����������� ������������������  catch()와����������� ������������������  동일한����������� ������������������  기능을����������� ������������������  하는����������� ������������������  메서드를����������� ������������������  

지원한다.����������� ������������������  

Page 41: JavaScript Promises

Promise.all

복수의 비동기 요청 - all

복수의����������� ������������������  비동기����������� ������������������  로직은����������� ������������������  Promise.all()을����������� ������������������  이용하면����������� ������������������  간단하게����������� ������������������  작성할����������� ������������������  수����������� ������������������  있다.����������� ������������������  

41  

Page 42: JavaScript Promises

Promise.all

복수의 비동기 요청 - all

복수의����������� ������������������  비동기����������� ������������������  로직은����������� ������������������  Promise.all()을����������� ������������������  이용하면����������� ������������������  간단하게����������� ������������������  작성할����������� ������������������  수����������� ������������������  있다.����������� ������������������  

42  

Promise.all([ ajax('/api/cards').then(JSON.parse), ajax('/api/insurances').then(JSON.parse) ]).then(function(value){ console.log(value); }).catch(function(error){ console.log(error); });   

Promise.all()는����������� ������������������  인자로����������� ������������������  promise����������� ������������������  객체를����������� ������������������  원소로����������� ������������������  가진����������� ������������������  배열을����������� ������������������  받는다.����������� ������������������  

처리가����������� ������������������  완료된����������� ������������������  후����������� ������������������  값����������� ������������������  순서는����������� ������������������  배열의����������� ������������������  순서와����������� ������������������  같다.����������� ������������������  

����������� ������������������  

하나����������� ������������������  명심해야할����������� ������������������  점은����������� ������������������  Promise.all()은����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  로직을����������� ������������������  순차적����������� ������������������  ����������� ������������������  

실행하지����������� ������������������  않고����������� ������������������  동시에����������� ������������������  실행한다는����������� ������������������  점이다.����������� ������������������  

function timer(delay){ return new Promise(function(resolve){ setTimeout(function(){ resolve(delay); }, delay); }) } var start = Date.now(); Promise.all([ timer(1), timer(32), timer(64), timer(128) ]).then(function(values){ console.log(Date.now() - start + 'ms'); console.log(values); });   

Page 43: JavaScript Promises

Promise.race

복수의 비동기 요청 - race

Promise.all()과����������� ������������������  마찬가지로����������� ������������������  promise����������� ������������������  객체를����������� ������������������  배열로����������� ������������������  전달����������� ������������������  받아����������� ������������������  ����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  로직을����������� ������������������  처리한다.����������� ������������������  ����������� ������������������  Promise.race()는����������� ������������������  Promise.all()과����������� ������������������  달리����������� ������������������  promise����������� ������������������  객체����������� ������������������  중����������� ������������������  하나����������� ������������������  만����������� ������������������  완료돼도����������� ������������������  다음����������� ������������������  동작으로����������� ������������������  넘어간다.����������� ������������������  

43  

Page 44: JavaScript Promises

Promise.race

복수의 비동기 요청 - race

Promise.all()과����������� ������������������  마찬가지로����������� ������������������  promise����������� ������������������  객체를����������� ������������������  배열로����������� ������������������  전달����������� ������������������  받아����������� ������������������  ����������� ������������������  복수의����������� ������������������  비동기����������� ������������������  로직을����������� ������������������  처리한다.����������� ������������������  ����������� ������������������  Promise.race()는����������� ������������������  Promise.all()과����������� ������������������  달리����������� ������������������  promise����������� ������������������  객체����������� ������������������  중����������� ������������������  하나����������� ������������������  만����������� ������������������  완료돼도����������� ������������������  다음����������� ������������������  동작으로����������� ������������������  넘어간다.����������� ������������������  

44  

function timer(delay){ return new Promise(function(resolve){ setTimeout(function(){ resolve(delay); }, delay); }) } var start = Date.now(); Promise.race([ timer(1), timer(32), timer(64), timer(128) ]).then(function(values){ console.log(Date.now() - start + 'ms'); console.log(values); });   

Page 45: JavaScript Promises

   PROMISES의 특징

Page 46: JavaScript Promises

항상 비동기로 처리되는 Promise

항상 비동기로 처리

46  

Promise.resolve()나����������� ������������������  resolve()를����������� ������������������  사용하면����������� ������������������  promise����������� ������������������  객체는����������� ������������������  바로����������� ������������������  Fulfilled����������� ������������������  상태가����������� ������������������  되므로����������� ������������������  then()으로����������� ������������������  등록한����������� ������������������  콜백����������� ������������������  함수도����������� ������������������  동기적으로����������� ������������������  호출될����������� ������������������  것이라����������� ������������������  예상된다.����������� ������������������  

Page 47: JavaScript Promises

항상 비동기로 처리되는 Promise

항상 비동기로 처리

Promise.resolve()나����������� ������������������  resolve()를����������� ������������������  사용하면����������� ������������������  promise����������� ������������������  객체는����������� ������������������  바로����������� ������������������  Fulfilled����������� ������������������  상태가����������� ������������������  되므로����������� ������������������  then()으로����������� ������������������  등록한����������� ������������������  콜백����������� ������������������  함수도����������� ������������������  동기적으로����������� ������������������  호출될����������� ������������������  것이라����������� ������������������  예상된다.����������� ������������������  

47  

var promise = new Promise(function(resolve){ console.log('inner promise'); resolve(42); }); promise.then(function(value){ console.log(value); }); console.log('outer promise');   

노트����������� ������������������  :����������� ������������������  ES6����������� ������������������  Promises����������� ������������������  사양에는����������� ������������������  promise����������� ������������������  객체의����������� ������������������  상태가����������� ������������������  이미����������� ������������������  정해져����������� ������������������  있다����������� ������������������  하더라도����������� ������������������  비동기로����������� ������������������  처리����������� ������������������  돼야����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  한다고����������� ������������������  정하고����������� ������������������  있다.����������� ������������������  

Page 48: JavaScript Promises

항상 비동기로 처리되는 Promise

동기와 비동기 혼재의 위험성

데이터를����������� ������������������  즉시����������� ������������������  사용할����������� ������������������  수����������� ������������������  있더라도����������� ������������������  절대로����������� ������������������  비동기����������� ������������������  콜백을����������� ������������������  동기적으로����������� ������������������  호출하면����������� ������������������  안된다.����������� ������������������  비동기����������� ������������������  콜백을����������� ������������������  동기적으로����������� ������������������  호출하면����������� ������������������  기대한����������� ������������������  연산의����������� ������������������  순서를����������� ������������������  방해하고����������� ������������������  예상치����������� ������������������  않은����������� ������������������  코드의����������� ������������������  간섭을����������� ������������������  초래할����������� ������������������  수����������� ������������������  있다.����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  ����������� ������������������  -����������� ������������������  이펙티브����������� ������������������  자바스크립트����������� ������������������  -����������� ������������������  

48  

function onReady(callback){ var readyState = document.readyState; if(readyState === 'interactive' || readyState === 'complete'){ callback(); }else{ window.addEventListener( 'DOMContentLoaded', callback ); } } onReady(function(){ console.log('DOM fully loaded and parsed'); }); console.log('starting...');   

if(readyState === 'interactive' || readyState === 'complete'){ setTimeout(fn, 0) }else{   

function onReady(){ return new Promise(function(resolve){ var readyState = document.readyState; if(readyState === 'interactive' || readyState === 'complete'){ resolve(); }else{ window.addEventListener( 'DOMContentLoaded', resolve); } }); } onReady().then(function(){ console.log('DOM fully loaded and parsed'); }); console.log('starting...');   

Page 49: JavaScript Promises

새로운 promise 객체를 반환하는 then

새로운 promise 객체를 반환

Promise����������� ������������������  로직을����������� ������������������  보면����������� ������������������  모두����������� ������������������  최초의����������� ������������������  promise����������� ������������������  객체에����������� ������������������  메서드를����������� ������������������  체인하는����������� ������������������  것����������� ������������������  처럼����������� ������������������  보인다.����������� ������������������  하지만����������� ������������������  실제로는����������� ������������������  then()과����������� ������������������  catch()����������� ������������������  모두����������� ������������������  새로운����������� ������������������  promise����������� ������������������  객체를����������� ������������������  생성해����������� ������������������  반환한다.����������� ������������������  

49  

Page 50: JavaScript Promises

새로운 promise 객체를 반환하는 then

새로운 promise 객체를 반환

Promise����������� ������������������  로직을����������� ������������������  보면����������� ������������������  모두����������� ������������������  최초의����������� ������������������  promise����������� ������������������  객체에����������� ������������������  메서드를����������� ������������������  체인하는����������� ������������������  것����������� ������������������  처럼����������� ������������������  보인다.����������� ������������������  하지만����������� ������������������  실제로는����������� ������������������  then()과����������� ������������������  catch()����������� ������������������  모두����������� ������������������  새로운����������� ������������������  promise����������� ������������������  객체를����������� ������������������  생성해����������� ������������������  반환한다.����������� ������������������  

50  

var promise = new Promise(function(resolve){ resolve(100); }); var thenPromise = promise.then(function(value){ console.log(value); }); var catchPromise = thenPromise.catch(function(error){ console.log(error); }); console.log(promise === thenPromise); console.log(thenPromise === catchPromise);   

onFulfilled  

onRejected   onRejected  

promise object promise object value

error error

then catch

Page 51: JavaScript Promises

새로운 promise 객체를 반환하는 then

새로운 promise 객체를 반환

Promise����������� ������������������  로직을����������� ������������������  보면����������� ������������������  모두����������� ������������������  최초의����������� ������������������  promise����������� ������������������  객체에����������� ������������������  메서드를����������� ������������������  체인하는����������� ������������������  것����������� ������������������  처럼����������� ������������������  보인다.����������� ������������������  하지만����������� ������������������  실제로는����������� ������������������  then()과����������� ������������������  catch()����������� ������������������  모두����������� ������������������  새로운����������� ������������������  promise����������� ������������������  객체를����������� ������������������  생성해����������� ������������������  반환한다.����������� ������������������  

51  

var promise = new Promise(function(resolve){ resolve(100); }); promise.then(function(value){ return value * 2; }); promise.then(function(value){ return value * 2; }); promise.then(function(value){ console.log(value); // 100 });   

var promise = new Promise(function(resolve){ resolve(100); }); promise.then(function(value){ return value * 2; }).then(function(value){ return value * 2; }).then(function(value){ console.log(value); // 100 * 2 * 2 });   

function anAsyncCall(){ var promise = Promise.resolve(); promise.then(function(){ // something do... }); return promise; }   

Page 52: JavaScript Promises

예외 처리가 되지 않는 onRejected

예외 처리가 되지 않는 경우

then()을����������� ������������������  이용해����������� ������������������  onFulfilled와����������� ������������������  onRejected를����������� ������������������  모두����������� ������������������  등록한다면����������� ������������������  예외����������� ������������������  처리가����������� ������������������  되지����������� ������������������  않는����������� ������������������  상황이����������� ������������������  발생한다.����������� ������������������  

52  

Page 53: JavaScript Promises

예외 처리가 되지 않는 onRejected

예외 처리가 되지 않는 경우

then()을����������� ������������������  이용해����������� ������������������  onFulfilled와����������� ������������������  onRejected를����������� ������������������  모두����������� ������������������  등록한다면����������� ������������������  예외����������� ������������������  처리가����������� ������������������  되지����������� ������������������  않는����������� ������������������  상황이����������� ������������������  발생한다.����������� ������������������  

53  

Promise.resolve(30).then(function(value){ throw new Error(value); }, function(error){ console.log('BAD'); console.log(error); }); Promise.resolve(20).then(function(value){ throw new Error(value); }).catch(function(error){ console.log('GOOD'); console.log(error); }); Promise.resolve(10).then(function(value){ throw new Error(value); }).then(undefined, function(error){ console.log('OK'); console.log(error); });   

Page 54: JavaScript Promises

콜백-헬과 무관한 Promise

만능의 도구가 아니다.

Promise는����������� ������������������  콜백-헬을����������� ������������������  해결할����������� ������������������  수����������� ������������������  있는����������� ������������������  만능의����������� ������������������  도구가����������� ������������������  아니다.����������� ������������������  통일된����������� ������������������  인터페이스로����������� ������������������  데이터를����������� ������������������  전달할����������� ������������������  수����������� ������������������  있는����������� ������������������  컨테이너로써����������� ������������������  장점을����������� ������������������  발휘하는����������� ������������������  것이다.����������� ������������������  

54  

?����������� ������������������  

Page 55: JavaScript Promises

콜백-헬과 무관한 Promise

만능의 도구가 아니다.

Promise는����������� ������������������  콜백-헬을����������� ������������������  해결할����������� ������������������  수����������� ������������������  있는����������� ������������������  만능의����������� ������������������  도구가����������� ������������������  아니다.����������� ������������������  통일된����������� ������������������  인터페이스로����������� ������������������  데이터를����������� ������������������  전달할����������� ������������������  수����������� ������������������  있는����������� ������������������  컨테이너로써����������� ������������������  장점을����������� ������������������  발휘하는����������� ������������������  것이다.����������� ������������������  

55  

some().then(function(){ // do something... }).then(function(){ // do something... }).then(function(){ // do something... }).then(function(){ // do something... }).catch(function(){ // do something... });   

Page 56: JavaScript Promises

콜백-헬과 무관한 Promise

만능의 도구가 아니다.

콜백-헬에����������� ������������������  빠진����������� ������������������  상태라면����������� ������������������  분석한����������� ������������������  모델이����������� ������������������  이미����������� ������������������  깨져있고,����������� ������������������  관심사를����������� ������������������  제대로����������� ������������������  나누지����������� ������������������  않았다는����������� ������������������  방증이다.����������� ������������������  ����������� ������������������  이는����������� ������������������  Promise로도����������� ������������������  해결할����������� ������������������  수����������� ������������������  없다.����������� ������������������  

56  

 커넥터 로직  비즈니스 로직  엔티티 로직  서비스 로직  DAO 로직  

스토리지  

엔티티  (DTO)  

DAO  

커넥터  

비즈니스  

서비스  

값 객체  

Page 57: JavaScript Promises

콜백-헬과 무관한 Promise

설계

•  사용자가����������� ������������������  /api/stores����������� ������������������  를����������� ������������������  GET����������� ������������������  요청하면����������� ������������������  상점����������� ������������������  리스트를����������� ������������������  반환한다.����������� ������������������  •  사용자가����������� ������������������  /api/stores/:id����������� ������������������  를����������� ������������������  GET����������� ������������������  요청하면����������� ������������������  상점을����������� ������������������  반환한다.����������� ������������������  •  데이터베이스엔����������� ������������������  상점����������� ������������������  테이블과����������� ������������������  카테고리����������� ������������������  테이블이����������� ������������������  별도로����������� ������������������  존재한다.����������� ������������������  

57  

Page 58: JavaScript Promises

콜백-헬과 무관한 Promise

설계

•  사용자가����������� ������������������  /api/stores����������� ������������������  를����������� ������������������  GET����������� ������������������  요청하면����������� ������������������  상점����������� ������������������  리스트를����������� ������������������  반환한다.����������� ������������������  •  사용자가����������� ������������������  /api/stores/:id����������� ������������������  를����������� ������������������  GET����������� ������������������  요청하면����������� ������������������  상점을����������� ������������������  반환한다.����������� ������������������  •  데이터베이스엔����������� ������������������  상점����������� ������������������  테이블과����������� ������������������  카테고리����������� ������������������  테이블이����������� ������������������  별도로����������� ������������������  존재한다.����������� ������������������  

58  

Stores  

Categories  

DB  Connector  

Market  client  

Page 59: JavaScript Promises

콜백-헬과 무관한 Promise

Store 클래스

Store����������� ������������������  클래스를����������� ������������������  작성한다.����������� ������������������  

59  

Page 60: JavaScript Promises

콜백-헬과 무관한 Promise

Store 클래스

Store����������� ������������������  클래스를����������� ������������������  작성한다.����������� ������������������  

60  

var Stores = function(connector){ this._connector = connector; }; Stores.prototype = { findAll : function(){ var self = this; return new Promise(function(resolve){ var stores = self._connector.where(); resolve(stores.items); }) }, findBy : function(id){ var self = this; return new Promise(function(resolve, reject){ var store = self._connector.get(parseInt(id, 10)); if(store){ resolve(store); }else{ reject(new Error('Not Found.')); } }); } }; module.exports = Stores;   

Page 61: JavaScript Promises

콜백-헬과 무관한 Promise

Categories 클래스

Categories����������� ������������������  클래스����������� ������������������  작성하기����������� ������������������  

61  

Page 62: JavaScript Promises

콜백-헬과 무관한 Promise

Categories 클래스

Categories����������� ������������������  클래스����������� ������������������  작성하기����������� ������������������  

62  

var Categories = function(connector){ this._connector = connector; }; Categories.prototype = { findAll : function(){ var self = this; return new Promise(function(resolve){ var categories = self._connector.where(); resolve(categories.items); }) }, findBy : function(id){ var self = this; return new Promise(function(resolve, reject){ var category = self._connector.where({_id : id}).items[0]; if(category){ resolve(category); }else{ reject(new Error('Not Found.')); } }); } }; module.exports = Categories;   

Page 63: JavaScript Promises

콜백-헬과 무관한 Promise

Market 클래스

Market����������� ������������������  클래스����������� ������������������  작성하기����������� ������������������  

63  

Page 64: JavaScript Promises

콜백-헬과 무관한 Promise

Market 클래스

Market����������� ������������������  클래스����������� ������������������  작성하기����������� ������������������  

64  

var Market = function(){ this._stores = new Stores(db.collection('stores')); this._categories = new Categories(db.collection('categories')); }; Market.prototype = { stores : function(){ return Promise.all([ this._stores.findAll(), this._categories.findAll() ]).then(function(values){ var stores = values[0], categories = values[1]; stores.forEach(function(store){ store.category = categories.find(function(category){ return category._id === store.category_id; }); }); return stores; }) },

계속����������� ������������������  >>����������� ������������������  

Page 65: JavaScript Promises

콜백-헬과 무관한 Promise

Market 클래스

Market����������� ������������������  클래스����������� ������������������  작성하기����������� ������������������  

65  

store : function(id){ var self = this, store = null; return this._stores.findBy(id).then(function(values){ store = values; return self._categories.findBy(store.category_id); }).then(function(category){ store.category = category; return store; }); } }; module.exports = Market;

Page 66: JavaScript Promises

콜백-헬과 무관한 Promise

최종

app.js에서����������� ������������������  Market����������� ������������������  객체����������� ������������������  사용하기����������� ������������������  

66  

router.route('/stores').get(function(req, res) { market.stores().then(function(stores){ res.json(stores); }).catch(function(err){ res.writeHead(404, {"Content-Type": "text/plain"}); res.end(err.message); }) }); router.route('/stores/:id').get(function(req, res) { market.store(req.params.id).then(function(store){ res.json(store); }).catch(function(err){ res.writeHead(404, {"Content-Type": "text/plain"}); res.end(err.message); }) });   

Page 67: JavaScript Promises

   Promises 직접 구현하기

Page 68: JavaScript Promises

시작하기 전에

핵심

68  

function doSomething(callback){ var value = 42; callback(null, value); }   

doSomething(function(error, value){ console.log('Got a value : ', value); });   

function doSomething(){ return { then : function(callback){ var value = 42; callback(value); } } }   

doSomething().then(function(value){ console.log('Got a value : ', value); });   

전통적인 콜백 패턴을 단순하게 변환한 것으로 큰 의미는 없어 보이지만, Promise의 근본적인 철학은 이미 다루고 있다.

Promise는 객체 내에 처리 결과를 보유한다.

Promise는 결과 값을 추상화한 객체를 전달한다.

Page 69: JavaScript Promises

스텝 1

Promise 클래스 정의

69  

new����������� ������������������  연산자를����������� ������������������  사용해����������� ������������������  Promise����������� ������������������  인스턴스를����������� ������������������  생성할����������� ������������������  수����������� ������������������  있어야����������� ������������������  하므로����������� ������������������  클래스를����������� ������������������  정의한다.����������� ������������������  

Page 70: JavaScript Promises

스텝 1

Promise 클래스 정의

70  

new����������� ������������������  연산자를����������� ������������������  사용해����������� ������������������  Promise����������� ������������������  인스턴스를����������� ������������������  생성할����������� ������������������  수����������� ������������������  있어야����������� ������������������  하므로����������� ������������������  클래스를����������� ������������������  정의한다.����������� ������������������  

var Promise = function(fn){ this._onFulfilled = null; fn(this._resolve.bind(this)); }; Promise.prototype = { then : function(onFulfilled){ this._onFulfilled = onFulfilled; }, _resolve : function(value){ this._onFulfilled(value); } };    

Page 71: JavaScript Promises

스텝 1

Promise 클래스 정의

71  

앞����������� ������������������  슬라이드에서����������� ������������������  구현한����������� ������������������  코드는����������� ������������������  동작하지����������� ������������������  않는다.����������� ������������������  resolve()가����������� ������������������  then()보다����������� ������������������  먼저����������� ������������������  호출되어����������� ������������������  그����������� ������������������   결과����������� ������������������   _onFulfilled는����������� ������������������   null이����������� ������������������   되어버리기����������� ������������������   때문이다.����������� ������������������   이����������� ������������������   문제를����������� ������������������   회피하기����������� ������������������   위해����������� ������������������  ����������� ������������������  setTimeout()을����������� ������������������  사용한다.����������� ������������������  ����������� ������������������  

Page 72: JavaScript Promises

스텝 1

Promise 클래스 정의

72  

앞����������� ������������������  슬라이드에서����������� ������������������  구현한����������� ������������������  코드는����������� ������������������  동작하지����������� ������������������  않는다.����������� ������������������  resolve()가����������� ������������������  then()보다����������� ������������������  먼저����������� ������������������  호출되어����������� ������������������  그����������� ������������������   결과����������� ������������������   _onFulfilled는����������� ������������������   null이����������� ������������������   되어버리기����������� ������������������   때문이다.����������� ������������������   이����������� ������������������   문제를����������� ������������������   회피하기����������� ������������������   위해����������� ������������������  ����������� ������������������  setTimeout()을����������� ������������������  사용한다.����������� ������������������  ����������� ������������������  

_resolve : function(value){ + var self = this;

+ setTimeout(function(){ self._onFulfilled(value); + }.bind(this), 1); }   

Page 73: JavaScript Promises

스텝 2

fulfilled 상태와 resolve

73  

setTimeout()은����������� ������������������  한계가����������� ������������������  있다.����������� ������������������  then()을����������� ������������������  비동기로����������� ������������������  호출하면����������� ������������������  다시����������� ������������������  _onFulfilled는����������� ������������������  null이����������� ������������������  된다.����������� ������������������  Promise에는����������� ������������������  상태가����������� ������������������  있다.����������� ������������������  이����������� ������������������  상태를����������� ������������������  이용하면����������� ������������������  setTimeout을����������� ������������������  제거하면서����������� ������������������  동기/비동기에����������� ������������������  상관없이����������� ������������������  then()을����������� ������������������  호출할����������� ������������������  수����������� ������������������  있다.����������� ������������������  ����������� ������������������  

Page 74: JavaScript Promises

스텝 2

fulfilled 상태와 resolve

74  

setTimeout()은����������� ������������������  한계가����������� ������������������  있다.����������� ������������������  then()을����������� ������������������  비동기로����������� ������������������  호출하면����������� ������������������  다시����������� ������������������  _onFulfilled는����������� ������������������  null이����������� ������������������  된다.����������� ������������������  Promise에는����������� ������������������  상태가����������� ������������������  있다.����������� ������������������  이����������� ������������������  상태를����������� ������������������  이용하면����������� ������������������  setTimeout을����������� ������������������  제거하면서����������� ������������������  동기/비동기에����������� ������������������  상관없이����������� ������������������  then()을����������� ������������������  호출할����������� ������������������  수����������� ������������������  있다.����������� ������������������  ����������� ������������������   var Promise = function(fn){ + this._state = 'pending'; + this._value = null; + this._deferred = null; this._onFulfilled = null; ... Promise.prototype = { then : function(onFulfilled){- this._onFulfilled = onFulfilled; + this._handle(onFulfilled); },

_resolve : function(value){ - setTimeout(function(){ - this._onFulfilled(value); - }.bind(this), 1);

+ this._value = value; + this._state = 'fulfilled';

+ if(this._deferred){ + this._handle(this._deferred); + } },  

계속����������� ������������������  >>����������� ������������������  

Page 75: JavaScript Promises

스텝 2

fulfilled 상태와 resolve

75  

setTimeout()은����������� ������������������  한계가����������� ������������������  있다.����������� ������������������  then()을����������� ������������������  비동기로����������� ������������������  호출하면����������� ������������������  다시����������� ������������������  _onFulfilled는����������� ������������������  null이����������� ������������������  된다.����������� ������������������  Promise에는����������� ������������������  상태가����������� ������������������  있다.����������� ������������������  이����������� ������������������  상태를����������� ������������������  이용하면����������� ������������������  setTimeout을����������� ������������������  제거하면서����������� ������������������  동기/비동기에����������� ������������������  상관없이����������� ������������������  then()을����������� ������������������  호출할����������� ������������������  수����������� ������������������  있다.����������� ������������������  ����������� ������������������  

+ _handle : function(onFulfilled){ + if(this._state === 'pending'){ + this._deferred = onFulfilled; + return false; + } + onFulfilled(this._value); + } };   

Page 76: JavaScript Promises

스텝 3

Promise의 체이닝

76  

Promise의����������� ������������������  상태는����������� ������������������  한번����������� ������������������  변화하면����������� ������������������  더이상����������� ������������������  변하지����������� ������������������  않는다.����������� ������������������  이����������� ������������������  조건을����������� ������������������  고려하여����������� ������������������  Promise����������� ������������������  체이닝을����������� ������������������  구현한다.����������� ������������������  

Page 77: JavaScript Promises

스텝 3

Promise의 체이닝

77  

Promise의����������� ������������������  상태는����������� ������������������  한번����������� ������������������  변화하면����������� ������������������  더이상����������� ������������������  변하지����������� ������������������  않는다.����������� ������������������  이����������� ������������������  조건을����������� ������������������  고려하여����������� ������������������  Promise����������� ������������������  체이닝을����������� ������������������  구현한다.����������� ������������������  

var Promise = function(fn){ ... - this._onFulfilled = null; ... Promise.prototype = { then : function(onFulfilled){ - this._handle(onFulfilled);  + var self = this;

+ return new Promise(function(resolve){ + self._handle({ + onFulfilled : onFulfilled, + resolve : resolve + }); + }.bind(this)); }, _resolve : function(value){ ... },

_handle : function(handler){ if(this._state === 'pending'){ this._deferred = handler; return false; } + var result = handler.onFulfilled(this._value); + handler.resolve(result); - onFulfilled(this._value); } };  

Page 78: JavaScript Promises

스텝 3

Promise의 체이닝

78  

then()의����������� ������������������  callback����������� ������������������  전달인자는����������� ������������������  옵셔널하게����������� ������������������  한다.����������� ������������������  

_handle : function(handler){ if(this._state === 'pending'){ this._deferred = handler; return false; } + if(!handler.onFulfilled){ + handler.resolve(this._value); + return false; + } var result = handler.onFulfilled(this._value); handler.resolve(result); }   

Page 79: JavaScript Promises

스텝 3

Promise의 체이닝

79  

then()으로����������� ������������������  등록한����������� ������������������  콜백은����������� ������������������  값����������� ������������������  뿐만����������� ������������������  아니라����������� ������������������  Promise����������� ������������������  객체도����������� ������������������  전달할����������� ������������������  수����������� ������������������  있어야����������� ������������������  한다.����������� ������������������  그리고����������� ������������������  그����������� ������������������  객체가����������� ������������������  해결한����������� ������������������  값이����������� ������������������  다음����������� ������������������  처리에����������� ������������������  전달된다.����������� ������������������  

Page 80: JavaScript Promises

스텝 3

Promise의 체이닝

80  

then()으로����������� ������������������  등록한����������� ������������������  콜백은����������� ������������������  값����������� ������������������  뿐만����������� ������������������  아니라����������� ������������������  Promise����������� ������������������  객체도����������� ������������������  전달할����������� ������������������  수����������� ������������������  있어야����������� ������������������  한다.����������� ������������������  그리고����������� ������������������  그����������� ������������������  객체가����������� ������������������  해결한����������� ������������������  값이����������� ������������������  다음����������� ������������������  처리에����������� ������������������  전달된다.����������� ������������������  

resolve : function(value){ + if(value && typeof value.then === 'function'){ + value.then(this._resolve.bind(this)); + return false; + } this._state = 'fulfilled'; this._value = value; if(this._deferred){ this._handle(this._deferred); } },     

Page 81: JavaScript Promises

스텝 4

rejected 상태와 reject

81  

무엇인가����������� ������������������  문제가����������� ������������������  생긴����������� ������������������  경우에는����������� ������������������  원인과����������� ������������������  함께����������� ������������������  거부(reject)해야����������� ������������������  한다.����������� ������������������  

계속����������� ������������������  >>����������� ������������������  

Page 82: JavaScript Promises

스텝 4

rejected 상태와 reject

82  

무엇인가����������� ������������������  문제가����������� ������������������  생긴����������� ������������������  경우에는����������� ������������������  원인과����������� ������������������  함께����������� ������������������  거부(reject)해야����������� ������������������  한다.����������� ������������������  

var Promise = function(fn){ ... fn( this._resolve.bind(this), + this._reject.bind(this) ); }; Promise.prototype = { then : function(onFulfilled, onRejected){ return new Promise(function(resolve, reject){ this._handle({ onFulfilled : onFulfilled, + onRejected : onRejected, resolve : resolve, + reject : reject }); }.bind(this)) }, + _reject : function(error){ + this._state = 'rejected'; + this._value = error; + if(this._deferred){ + this._handle(this._deferred); + } + }, 계속����������� ������������������  >>����������� ������������������  

Page 83: JavaScript Promises

스텝 4

rejected 상태와 reject

83  

무엇인가����������� ������������������  문제가����������� ������������������  생긴����������� ������������������  경우에는����������� ������������������  원인과����������� ������������������  함께����������� ������������������  거부(reject)해야����������� ������������������  한다.����������� ������������������  

_handle : function(handler){ + var callback = null; ... + if(this._state === 'fulfilled'){ + callback = handler.onFulfilled; + }else{ + callback = handler.onRejected; + } + if(!callback){ + if(this._state === 'fulfilled'){ + handler.resolve(this._value); + }else{ + handler.reject(this._value); + } + return false; + }

var result = callback(this._value); ... };  

Page 84: JavaScript Promises

스텝 4

예기치 못한 에러

84  

Promise는����������� ������������������  예상����������� ������������������  밖의����������� ������������������  예외를����������� ������������������  대응하고����������� ������������������  적절히����������� ������������������  거부할����������� ������������������  수����������� ������������������  있어야����������� ������������������  한다.����������� ������������������   var Promise = function(fn){ this._state = 'pending'; this._value = null; this._deferred = null; + try{ fn( this._resolve.bind(this), this._reject.bind(this) ); + }catch(error){ + this._reject(error); + } }; 

_handle : function(handler){ var callback = null, + result = null; ... + try{ + result = callback(this._value); + }catch(error){ + handler.reject(error); + return false; + } handler.resolve(result); }  

Page 85: JavaScript Promises

스텝 5

항상 비동기로 호출

85  

Promise는����������� ������������������  항상����������� ������������������  비동기로����������� ������������������  호출돼야����������� ������������������  한다.����������� ������������������  

Page 86: JavaScript Promises

스텝 5

항상 비동기로 호출

86  

Promise는����������� ������������������  항상����������� ������������������  비동기로����������� ������������������  호출돼야����������� ������������������  한다.����������� ������������������  

_handle : function(handler){ var callback = null, result = null, + self = this; if(this._state === 'pending'){ this._deferred = handler; return false; } + setTimeout(function(){ ... + }, 0); }  

Page 87: JavaScript Promises

<참고자료>

http://blog.coderifleman.com/post/102749244059

http://www.hanbit.co.kr/ebook/look.html?isbn=9788968487293����������� ������������������  

http://www.mattgreer.org/articles/promises-in-wicked-detail/����������� ������������������  

Page 88: JavaScript Promises

Thank you.