ES6的promise、Generator、async和回调函数的区别

80 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第26天juejin.cn/post/712312…

本章节给大家介绍一下ES6的promise、Generator、async和回调函数的区别,即它们的优缺点。

异步

所谓"异步",简单说就是一个任务不是连续完成的,可以理解成该任务被人为分成两段,先执行第一段,然后转而执行其他任务,等做好了准备,再回过头执行第二段。

回调函数

JavaScript 语言对异步编程的实现,就是回调函数。所谓回调函数,就是把任务的第二段单独写在一个函数里面,等到重新执行这个任务的时候,就直接调用这个函数。回调函数的英语名字callback,直译过来就是"重新调用"。

回调函数本身并没有问题,它的问题出现在多个回调函数嵌套。

代码不是纵向发展,而是横向发展,很快就会乱成一团,无法管理。因为多个异步操作形成了强耦合,只要有一个操作需要修改,它的上层回调函数和下层回调函数,可能都要跟着修改。这种情况就称为"回调函数地狱"(callback hell)。

回调函数主要用来封装异步任务第二段,我个人理解为从服务器请求回来数据之后,就开始执行回调函数,并把请求回来的数据当作参数传到回调函数里。如果有多个异步任务,那么会出现回调地狱的情况,整个代码层层嵌套,并且还会出现强耦合现象。如果修改了某一层的变量,该函数的上下环境都有可能作出修改。

优点:使用起来也比较简单。

Promise

Promise就是为了解决回调地狱和强耦合的现象提出的。它不是新的语法功能,而是一种新的写法,允许将回调函数的嵌套,改成链式调用。把异步第一段封装在Promise里,第二段我们可以使用then方法对请求回来的数据进行处理,而且可以then方法可以进行链式调用。使得异步任务以同步形式呈现。

缺点:Promise 的写法只是回调函数的改进,使用then方法以后,异步任务的两段执行看得更清楚了,除此以外,并无新意。

Promise 的最大问题是代码冗余,原来的任务被 Promise 包装了一下,不管什么操作,一眼看去都是一堆then,原来的语义变得很不清楚。

Generator函数

优点:Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。Generaot能够暂停执行和恢复执行,这是它能封装异步的根本原因。只要遇到yield语句,任务就会进入暂停状态,再次调用next方法,又会进入激活状态。而且它可以实现数据的交换。netx方法返回的value值,就是Generator传输出来的数据,next方法里面的参数,可以传入到Generator函数里,实现数据交换。使异步任务以同步形式呈现,看起来代码简洁。

缺点:Generator 函数将异步操作表示得很简洁,但是流程管理却不方便(即何时执行第一阶段、何时执行第二阶段)。

async函数

async 函数是什么?一句话,它就是 Generator 函数的语法糖。 实现原理:就是将Generator函数和自动执行生成器,封装在了一个函数里

优点: (1)内置执行器。 (2)更好的语义。 (3)更广的适用性。 (4)返回值是 Promise。 里面有await语句,该语句后面直接跟Promise的话,await的返回值就是Promise成功状态返回的异步数据,就不需要像Generator函数在调用其他方法,把数据传输进来,可以直接在async函数里使用第一次请求回来的数据。它的整个写法,除了有异步结果,与普通函数没有任何区别,使异步任务看起来更像是在执行同步任务。

async函数的语法规则总体上比较简单,难点是错误处理机制。