사실 Generator 라는걸 처음 접했을 땐 진짜 뭥미... 했었다... ㅋㅋ
그런데 python 에서도 scala 에서도 generator 라는 개념이 있더라. +_+ 그리고 java 에서도 generator 형태로 코드를 짜는 방법도 "java generator" 라고 검색하면 많이 있더라 :)
* python generator : http://bluese05.tistory.com/56
* java generator : https://www.codeproject.com/Articles/793374/Generators-with-Java
* scala generator : http://notes.backgroundsignal.com/Generators_in_Scala.html
위에 javascript generator : ... 라고 적고 싶지만! 이건 내 블로그에서 설명할거니까 빼자 ㅎㅎ
Sample Code
class Member { *gen() { yield 10; yield 20; } } let obj = new Member(); let genObj = obj.gen(); let result = genObj.next(); console.log(result); // { value: 10, done: false } let result = genObj.next(); console.log(result); //{ value: 20, done: false } result = genObj.next(); console.log(result); // { value: undefined, done: true }
가장 이해하기 좋은 예제가 아닐까... ㅎㅎ
Generator function 은 안에 더이상 yield 할게 없을 때까지 yield 한다. 그리고 항상 return 의 형태는 { value : xxx, done: false/true } 형태이다.
value : yield 된 값을 의미
done : 더이상 yield 할게 없을 경우 true, 더 남아 있을 경우 false 가 반환된다.
Generator funciton 을 이용한 iterator 구현
let fibonacci = { *[Symbol.iterator]() { let pre = 0, cur = 1 for (;;) { [ pre, cur ] = [ cur, pre + cur ] yield cur } } } for (let n of fibonacci) { if (n > 1000) break console.log(n) }
Symbol ... 을 아직 배우지 않아 혼돈 스러울 수 있을것 같은데 일단은 "구현체 안에 *[Symbol.iterator]() 이 있으면 for-of 구문에 사용할 수 있다." 정도로만 이해해 놓자. fibonacci 가 Array 혹은 Array-like 가 아님에도 불구하고 for of 에서 사용되는 것을 볼 수 있다. 그리고 for 문에 돌면서 generator function 인 Symbol.iterator 가 계속해서 호출되는 것을 볼 수 있다.
Generator function 을 이용한 Control-flow
// generic asynchronous control-flow driver function async (proc, ...params) { var iterator = proc(...params) return new Promise((resolve, reject) => { let loop = (value) => { let result try { result = iterator.next(value) } catch (err) { reject(err) } if (result.done) resolve(result.value) else if ( typeof result.value === "object" && typeof result.value.then === "function") result.value.then((value) => { loop(value) }, (err) => { reject(err) }) else loop(result.value) } loop() }) } // application-specific asynchronous builder function makeAsync (text, after) { return new Promise((resolve, reject) => { setTimeout(() => resolve(text), after) }) } // application-specific asynchronous procedure async(function* (greeting) { let foo = yield makeAsync("foo", 300) let bar = yield makeAsync("bar", 200) let baz = yield makeAsync("baz", 100) return `${greeting} ${foo} ${bar} ${baz}` }, "Hello").then((msg) => { console.log("RESULT:", msg) // "Hello foo bar baz" })
마지막 async 함수에서 makeAsync 라는 함수들이 호출되는데 이들이 모두 Promise 를 리턴하는 것을 볼 수 있다. promise 를 yield 시키게 되면 리턴된 promise 는 마치 syncronized 하게 코드가 동작하는 것을 볼 수 있다. 이러한 원리를 이용해 나오는 node.js library 가 바로 Co routine 이다.
( 참조 : https://github.com/tj/co )
'ECMAScript 2015, ECMAScript 6th Edition' 카테고리의 다른 글
11. Array Object (0) | 2016.09.27 |
---|---|
10. Object assign (0) | 2016.09.27 |
9. for of (0) | 2016.09.25 |
8. Enhanced Object ProPerties (0) | 2016.09.15 |
7. destructuring (0) | 2016.09.13 |