所谓 "异步", 简单说就是一个任务不是连续完成的, 可以理解成该任务被人为分成两段, 先执行第一段, 然后转而执行其他任务, 等做好了准备, 再回过头执行第二段, 这种不连续的执行, 就叫做异步. 相应地, 连续的执行就叫做同步.
Promise 的写法只是回调函数的改进, 使用 then 方法以后, 异步任务的两段执行看得更清楚了, 除此以外, 并无新意. Promise 的最大问题是代码冗余, 原来的任务被 Promise 包装了一下, 不管什么操作, 一眼看去都是一堆 then, 原来的语义变得很不清楚, 更好的方法是:
Generator 函数:
传统的编程语言, 早有异步编程的解决方案(其实是多任务的解决方案). 其中有一种叫做 "协程"(coroutine), 意思是多个线程互相协作, 完成异步任务. 协程有点像函数, 又有点像线程. 它的运行流程大致如下.
第一步, 协程 A 开始执行.
第二步, 协程 A 执行到一半, 进入暂停, 执行权转移到协程 B.
第三步,(一段时间后)协程 B 交还执行权.
第四步, 协程 A 恢复执行.
上面流程的协程 A, 就是异步任务, 因为它分成两段 (或多段) 执行.
Generator 函数是 ES6 提供的一种异步编程解决方案, 是协程在 ES6 的实现, 最大特点就是可以交出函数的执行权(即暂停执行), 但属于不完全实现. Generator 函数被称为 "半协程"(semi-coroutine), 意思是只有 Generator 函数的调用者, 才能将程序的执行权还给 Generator 函数. 如果是完全执行的协程, 任何函数都可以让暂停的协程继续执行.
调用 Generator 函数, 返回一个遍历器对象, 代表 Generator 函数的内部指针. 以后, 每次调用遍历器对象的 next 方法, 就会返回一个有着 value 和 done 两个属性的对象. value 属性表示当前的内部状态的值, 是 yield 表达式后面那个表达式的值; done 属性是一个布尔值, 表示是否遍历结束.
由于 Generator 函数返回的遍历器对象, 只有调用 next 方法才会遍历下一个内部状态, 所以其实提供了一种可以暂停执行的函数. yield 表达式就是暂停标志. yield 表达式只能用在 Generator 函数里面, 用在其他地方都会报错.
Generator 函数的自动执行: 重点是自动执行需要一种机制, 当异步操作有了结果, 能够自动交回执行权.
下面是一个基于 promise 对象的自动执行:
Generator 函数里 yield 后面要跟 promise 对象
代码上主要就是判断 done 属性是否为 true, 是否遍历完了. 否, 就自调用函数, 把值接着 next()传下去.
async 函数:
ES2017 (ES8)标准引入了 async 函数, 使得异步操作变得更加方便.
async 函数是什么? 一句话, 它就是 Generator 函数的语法糖.
基本用法: async 函数返回一个 Promise 对象, 可以使用 then 方法添加回调函数. 当函数执行的时候, 一旦遇到 await 就会先返回, 等到异步操作完成, 再接着执行函数体内后面的语句.
请求并发执行: 可以使用 Promise.all 方法
async 函数的实现原理: 就是将 Generator 函数和自动执行器, 包装在一个函数里.
参考文章链接:
ECMAScript 6 入门( 阮一峰)
来源: http://www.jianshu.com/p/ca377788b708