
对于解决异步的诸多方式,只是在处理异步问题上更加直观,并没有改变js是单线程语言,以及event loop的运行机制
promise
这里不会具体讲promise的用法,只记录自己感觉重要的地方
1. 注意事项
1.1 使用promise封装异步函数的时候,resolve和reject是在回调函数里面执行的。
1.2 当一个promise对象返回一个promise对象时,后面的then会作为这个返回的promise对象的第一个then处理。看代码:
promise.then(res => {
   console.log(res)
   return new Promise((resolve,reject) => {...})
        }).then(res => {
           // 这个res就是上一个then中返回的promise对象的resolve的值
           // ...
         })2. 重要的API
2.1 Promise.all:将所有指定的promise都执行完,再进行下一步操作。看代码:
  // promise1,promise2是传入的promise对象,是以数组的形式
  Promise.all([promise1,promise2]).then(res => {
    // res是一个数组,按顺序包含传入promise对象的resolve值
    console.log(res[0])
    console.log(res[1])
  })2.2 Promise.race:对于指定的promise对象,只要其中有一个完成了,就执行下一步。看代码:
Promise.race([promise3,promise4]).then(res => {
  // res是最先完成的promise对象的resolve值
   console.log(res)
 })2.3 Promise.resolve:将thenable对象转换为Promise对象,看代码:
 // 什么是 thenable 对象呢?
const thenable = {
// 就是拥有 then 属性,且属性值是如下格式的函数的对象
  then: (resolve,reject) => {
     if (success) {
        resolve(...)  
      } else {
        reject(...)
      }
    }
 }
  // 变为promise对象
let thenPromise = Promise.resolve(thenable)
thenPromise.then(res => {...})3. 所遵循的Promise/A+规范
这是由 CommonJS 组织制定的异步模式编程规范,promise功能的实现就是根据它来实现的
3.1 一个promise对象只有三种状态:等待pending、fulfilled已完成、已失败rejected。状态的转换只能是:pending ---> fulfilled / pending ---> rejected
3.2 then必须返回一个promise对象(这样才能实现链式调用啊!),接受两个参数,第一个是成功时的回调,第二个是失败时的回调(对于失败的回调不常用,一般用catch代替)
Generator
其实Generator并不是用来处理异步问题的,只不过使其与异步产生关联而已
1. Generator简介
1.1 Generator函数执行时,并不是立即执行函数内部的代码,而是返回一个对象(iterator对象)
1.2 执行过程是:调用next方法,会一直执行下去,直到遇到yield或者return,然后执行yield或者return后面的表达式,并且都有返回值:对于遇到yield是{value: ..., done: false},对于return是{value: ..., done: true}
2. Iterator遍历器对象
2.1 Iterator对象是一个指针对象,实现类似于单项链表的数据结构,通过next()将指针指向下一个节点
2.2 具有[Symbol.iterator]属性的对象可以生成iterator对象(见如下代码),从而可以使用for...of或者next()方法取值。原生具有[Symbol.iterator]属性的数据结构有:Array、like-Array(类数组对象)、Set、Map
let arr = [1,2,3]
// 生成iterator对象
// 可以看出对象[Symbol.iterator]属性返回的是一个函数
let iterArr = arr[Symbol.iterator]()3. Generator注意事项
3.1 yield*后可跟一个Generator对象,并且会把它其中的yield按照规则来一步一步执行。当有多个Generator串联使用的时候,可以使用yield*
4. Thunk函数
4.1 只有一个参数的函数,而且这个参数是一个callback函数,这样的函数就是Thunk函数。看代码:
// 这是一个读取文件的函数,有三个参数
function readFile(filename,'utf-8',(err,data) => {...})
// Thunk化
const thunk = function(filename,codeType) {
return function(callback) {
    readFile(path,codeType,callback)
  }
 }
// readFileThunk就是一个Thunk函数
const readFileThunk = thunk('test.json','utf-8')5. 结合Thunk函数和Generator函数
上面说过Generator函数本身与异步没啥关系,但是要是将Thunk函数与Generator结合起来,就可以用来处理异步了,传入Thunk函数的callback,正好可以作为异步函数的回调
1. 手动执行,看代码:
  function* G() {
       const res = yield thunk('test.json','utf-8')
       console.log('res: ',res)
     }
     const g = G()
     g.next().value((err,data) => {
       g.next(data)
     })2. 自动执行,看代码:
 // 上面只是进行一个thunk函数的操作,若遇到多个,那又要嵌套着写,很麻烦
     // 于是自执行函数出现了
     function autoGenerator(G) {
       // 生成iterator对象
       const g = G()
       function next(err,data) {
         const res = g.next(data)
         if (res.done) {
           // 如果执行完就return
           return
         }
         res.value(next)
       }
       // 先自执行一次,启动iterator
       next()
     }async-await
Generator的语法糖,更加易读!
1. function* ---> async function、yield ---> await。看代码:
  async function asyncFun() {
     const res1 = await new Promise(...)
     const res2 = await new Promise(...)
     console.log('res1: ',res1)
     console.log('res2: ',res2)
     return 'done'
   }2. async函数返回promise,then后取到的值就是done