在js中需要将异步方法同步的时候, 经常使用的是async
和await
, 或者用Promise
偶然在dvajs中看到其使用yield
迭代器实现了同步的效果, 例如
1 2 3 4 5 6 7 8 9 10 11 function * f ( ){ var a = Promise .resolve (1 ); console .log (a); var ra = yield a; console .log (ra); var b = Promise .resolve (2 ); console .log (b); var rb = yield b; console .log (rb); return "success" ; }
当然直接运行不能得到预期的效果, Promise
没用同步执行, yield
返回的结果也是undefined
, 因为还缺少对其的一层封装, 或者说还缺少个执行器
1 2 3 4 var it = f ();it.next (); it.next (); it.next ();
传统的迭代器, 是这样使用的
1 2 3 4 5 6 7 8 9 function * range ( ){ for (let i=0 ;i<n;i++){ yield i; } } var it = range ();console .log (it.next ().value ); console .log (it.next ().value ); console .log (it.next ().value );
如下封装, 在每一次yield
返回的Promise
的then
中进行下一次迭代, 并把结果传入 g.next(r)
, 迭代函数的next(r)
中的参数r
会成为函数体中yield
标识的表达式的返回值, 从而达到类似await
的效果
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 27 28 29 function async (g ) { var ctx = this ; return new Promise (function (resolve, reject ) { g = g.apply (ctx); next (); function next (r ) { var result = g.next (r); if (result.done ){ return resolve (result.value ); } result.value .then (next); } }); } async (function *(){ var a = Promise .resolve (1 ); console .log (a); var ra = yield a; console .log (ra); var b = Promise .resolve (2 ); console .log (b); var rb = yield b; console .log (rb); return "success" ; }).then (v => { console .log (v) });