[Javascript]使用Generator函数创建你自己的异步函数

欢迎来到佳佳doubi小课堂~在这里你可以学到实用又错误的知识×。

好久没写正经的博文了,让我来正经一下。

使用Generator函数来创建你的异步函数,先说明一下原理。

Generator函数是ES6里的新函数类型,函数定义写作这样

看到没,在函数名和function之间多了一个*号,这不是我写错了,是Generator函数的标志,这个*号其实也可以贴着函数名写 function *a(){},也可以不加空格 function*a(){},不过还是推荐把它贴着function写,这样既不会影响一些编辑器里的高亮,也不会降低代码可读性。

那么为什么Generator函数可以用来做异步函数呢?

我们普通的函数都是顺序执行的,像这样

会在控制台依次输出

当然这不能说明什么,不过可以留着和接下来的示例代码做对比。

 

Generator函数有一个和普通函数不同的地方,它里面可以出现一个叫做’yield’的关键字。
yield关键字可以让函数执行到它前面以后暂停,飞出当前的执行环境去做其他事,当这个Generator的next()方法被调用的时候,js又会回到这个函数环境里,继续执行代码。

注:关于’yield前面’的解释
yield前面指的并不是带有yield这个关键字的语句的前面一句,而是跟在yield关键字后面的语句。在Generator函数被用来做异步函数时yield一般都会以这样的形式出现:

这个异步函数指的就是yield的前面,因为它的执行顺序是到那个异步函数之后就暂停,当Generator的next被调用的时候此处的yield就会获取到next函数的参数,然后赋值给result变量,然后接着执行下去。当然,如果yield单独成句的话,那就相当于执行到前一句暂停了。

上面的注释可能打得太早了,你如果原本不知道Generator是什么的话可能会看不懂,不过你可以先往下看,然后再倒上来看一次。

Generator函数的使用方法要先说明一下,虽然在这篇文章里这不是主要的,我完全可以直接丢个代码出来说说怎么写个异步函数就可以完事了,不过本着提高误导教程的biger的精神,我决定写详细一些。

Generator的定义上面说过了

Generator的调用(这里的代码接着上面的环境)

以上代码的过程可以解释如下

可以看到,正是因为可以随意出入函数环境的特性,使Generator可以用来制作自己的异步函数。
相比使用setTimeout来模拟异步的好处就是可以保持函数的变量环境,不用让setTimeout带着一大堆参数一起跑了。

首先,我要定义一个特别的函数(这是我的做法,实际做法多种多样)

它是啥?它是用来帮我们来调用next函数的函数,把要异步执行的过程丢给它,然后函数就会自己异步执行起来,而不用我们来一个个调用next了。

然后可以开始制作我们可爱的异步函数啦。

老实说我写到这里开始有些后悔叫它异步函数了,因为其实所有过程还是在js主进程里执行的,更准确的说这应该叫协程,可以算是个模拟的多线程。不过也没关系啦,反正都这么写了。。。不太讲究的话其实表面来看是一个意思。

然后执行之,测试异步函数的话,一个个执行肯定是没有意思的,所以要同时调用多个来测试,于是就这样

猜猜结果是什么?

在我的node里输出如下

可以看出这5个调用全部被拆分了,而不是一个执行完再执行另外一个。而且函数内部环境是一直保存到执行结束的。

===================================================
我知道你们最喜欢例子,来来来,往这看

  • 在浏览器里支持像nextTick这种空闲时调用函数的方法也有来着,不过我忘了,而且支持额浏览器似乎也很有限。所以在浏览器环境中使用这种方法的可能不多,如果你想,可以用setTimeout来调用letmenext,一样可以达到这样的效果。
  • 还有其它任何异步函数都可以用来在callback的位置传递letmenext(要注意,传递letmenext作为回调的函数必须确保只会执行它一次,否则会扰乱运行结构)。
  • 也可以用这种异步方法来做动画效果,搭配定时函数,可以把动画节点依次写下去,配合css变换。而不用一个个setTimeout嵌套下去,变成一团难看的代码。
  • 说到动画效果,requestAnimationFrame函数也可以用来触发,不过受限于屏幕刷新率和绘图速度。
    还有一个用法就是可以把一系列异步函数写在一排里,而不用层层嵌套。代码好看多了喵!
  • 一般这样的伪多线程模式用在会耗时很久的函数上,防止阻塞其它事务。在函数里适当的地方放一个暂停即可异步之。

各种异步函数使用方法自己研究去吧,我才不会再写一个例子出来呢CwC。

参考:





如文中无特殊说明,本站均使用以下协议:知识共享许可协议
知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。

本博客使用Disqus评论系统,如果看不到评论框,请尝试爬墙。