JS异步编程 (2) - Promise、Generator、async/await (2)

首先我们先来看下使用Generator函数能达到怎样的效果。

// 使用Generator函数进行异步编程 function* oneGenerator() { yield asyncFn1(); yield asyncFn2(); yield normalFn3(); } // 我们来对比一下Promise asyncFn1().then(asyncFn2).then(normalFn3);

我们可以看出使用Generator函数进行异步编程更像是在写同步任务,对比Promise少了很多次then方法的调用。

 

好,那么接下来我们就来看下如何实际使用Generator函数进行异步编程。

 

这里我要特别说明一下,事实上Generator函数不像Promise一样是专门用来解决异步处理而产生的,人们只是使用其特性来产出了一套异步的解决方案,所以使用Generator并不像使用Promise一样有一种开箱即用的感觉。其更像是在Promise或者回调这类的解决方案之上又封装了一层,让你可以像上面例子里一样去那么写。

我们还是具体来看下上面的例子,我们知道单写一个Generator是不能运行的对吧,我们需要执行他并且使用next方法来让他分步执行,那么什么时候去调用next呢?答案就是我们需要在异步完成时去调用next。我们来按照这个思路补全上面的例子。

var g; function asyncFn() { setTimeout(function(){ g.next(); }, 1000) } function normalFn() { console.log('normalFn run'); } function* oneGenerator() { yield asyncFn(); return normalFn(); } g = oneGenerator(); g.next(); // 这里在我调用next方法的时候执行了asyncFn函数 // 然后我们的希望是在异步完成时自动去再调用g.next()来进行下面的操作,所以我们必须在上面asyncFn函数体内的写上g.next(); 这样才能正常运行。 // 但其实这样是比较奇怪的,因为当我定义asyncFn的时候其实是不知道oneGenerator执行后叫什么名儿的,即使我们提前约定叫g,但这样asyncFn就太过于耦合了,不仅写法很奇怪而且耦合太大不利于扩展和重用。反正总而言之这种写法很不好。

那么怎么解决呢,我们需要自己写个方法,能自动运行Generator函数,这种方法很简单在社区里有很多,最著名的就是大神TJ写的co模块,有兴趣的同学可以看下其源码实现。这里我们简单造个轮子:

// 如果我们想要去在异步执行完成时自动调用next就需要有一个钩子,回调函数的callback或者Promise的then。 function autoGenerator(generator){ var g = generator(); function next(){ var res = g.next(); // {value: xxx, done: xxx} if (res.done) { return res.value; } if(typeof res.value === 'function'){ // 认为是回调 res.value(next); }else if(typeof res.value === 'object' && typeof res.value.then === 'function'){ // 认为是promise res.value.then(function(){ next(); }) }else{ next(); } } next(); } // ---- function asyncFn1(){ console.log('asyncFn1'); return new Promise(function(resolve){ setTimeout(function(){ resolve(); }, 1000) }) } function asyncFn2() { console.log('asyncFn2'); return function(callback){ setTimeout(function(){ callback(); }, 1000); } } function normalFn() { console.log('normalFn'); } function* oneGenerator() { yield asyncFn1(); yield asyncFn2(); yield normalFn(); } autoGenerator(oneGenerator);

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssjpy.html