promise的用法示例:
1 2 3 4 5 Promise .resolve (a).then (b => { }).then (c => { })
换为async/await用法示例:
1 2 3 4 5 async () => { const a = await Promise .resolve (a) const b = await Promise .resolve (b) const c = await Promise .resolve (c) }
换为Generator函数的写法:
1 2 3 4 5 6 7 8 9 10 11 function *myGenerator ( ) { yield '1' ; yield '2' ; return '3' ; } const genFn = myGenerator ();genFn.next (); genFn.next (); genFn.next (); genFn.next ();
还可以通过next方法传入参数,让Generator函数的yield语句具有返回值。
1 2 3 4 5 6 7 8 9 10 function *myGenerator ( ) { console .log (yield '1' ); console .log (yield '2' ); console .log (yield '3' ); } const genFn = myGenerator ();genFn.next ('test1' ); genFn.next ('test2' ); genFn.next ('test3' );
不同点:
async/await是自动执行,不需要手动调用next()执行下一步骤。
async返回的是Promise对象,Generator函数返回生成器对象。
await能够返回Promise执行resolve/reject的值。
一、自动执行/手动执行
手动执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function *myGenerator ( ) { yield Promise .resolve ('a' ); yield Promise .resolve ('b' ); yield Promise .resolve ('c' ); } const gen = myGenerator ();gen.next ().value .then (a => { console .log (a); gen.next ().value .then (b => { console .log (b); gen.next ().value .then (c => { console .log (c) } }) })
自动执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function run (generator ) { const gen = generator (); function _next (value ) { const result = gen.next (); if (result.done ) return result.value ; result.value .then (res => { _next (res); }) } _next (); } function *generator ( ){ console .log (yield Promise .resolve ('a' )); console .log (yield Promise .resolve ('b' )); console .log (yield Promise .resolve ('c' )); }; run (generator);
二、返回Promise和捕获异常
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 30 31 32 33 34 35 36 37 function run (generator ) { return new Promise ((resolve, reject ) => { var gen = generator (); function _next (val ) { try { var result = gen.next (val); } catch (error) { return reject (error); } if (result.done ) { return resolve (result.value ); } Promise .resolve (result.value ).then (res => { _next (res); }, error => { gen.throw (error); }) } _next (); }) } function * myGenerator ( ) { try { console .log (yield Promise .resolve (1 )) console .log (yield 2 ) console .log (yield Promise .reject ('error' )) } catch (error) { console .log (error) } } const value = run (myGenerator);
Generator
结合上面说的async/await不同点,我们可以知道Generator具有的特点
调用Generator函数,并不会马上执行它里面的语句,而是返回一个这个生成器的迭代器(iterator)对象。
可以分段执行,通过调用next()方法,执行下一个步骤。
next()方法固定的返回一个对象,对象里面的value是当前步骤yield后面的值,done可以判断Generator函数是否执行完毕。
一、switch 模拟 缺点需要每次传参
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function gen$ (nextStep ) { while (1 ) { switch (nextStep) { case 0 : return 'result1' ; case 2 : return 'result2' ; case 4 : return 'result3' ; case 6 : return undefined ; } } } console .log (gen$ (2 ));
二、闭包,无需传参,调用一次,执行一次
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 function gen$2 ( ) { var nextStep = 0 ; return function ( ){ while (1 ) { switch (nextStep) { case 0 : nextStep = 2 ; return 'result1' ; case 2 : nextStep = 4 ; return 'result2' ; case 4 : nextStep = 6 ; return 'result3' ; case 6 : return undefined ; } } } } const fn = gen$2 ()fn (); fn (); fn (); fn ();
三、使用全局变量控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var context = { next : 0 , prev : 0 } function gen$ (_context ) { while (1 ) { switch (_context.prev = _context.next ) { case 0 : _context.next = 2 ; return 'result1' ; case 2 : _context.next = 4 ; return 'result2' ; case 4 : _context.next = 6 ; return 'result3' ; case 6 : return undefined ; } } }
四、next()方法改变执行步骤
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 30 31 var context = { next : 0 , prev : 0 } function gen$ (_context ) { while (1 ) { switch (_context.prev = _context.next ) { case 0 : _context.next = 2 ; return 'result1' ; case 2 : _context.next = 4 ; return 'result2' ; case 4 : _context.next = 6 ; return 'result3' ; case 6 : return undefined ; } } } var gen = function ( ) { return { next : function ( ) { value = gen$ (context); return value; } } }
五、添加状态和改变状态并返回一个对象
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 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 function gen$ (_context ) { while (1 ) { switch (_context.prev = _context.next ) { case 0 : _context.next = 2 ; return 'result1' ; case 2 : _context.next = 4 ; return 'result2' ; case 4 : _context.next = 6 ; return 'result3' ; case 6 : case 'end' : return _context.stop (); } } } var context = { next : 0 , prev : 0 , done : false , stop : function stop ( ) { this .done = true } } let gen = function ( ) { return { next : function ( ) { value = context.done ? undefined : gen$ (context) done = context.done return { value, done } } } } var g = gen ()console .log (g.next ())console .log (g.next ())console .log (g.next ())console .log (g.next ())
参考:
https://juejin.cn/post/6844904096525189128#heading-14
https://zhuanlan.zhihu.com/p/216060145