5

Promise

Promise 对象是一个代理对象(代理一个值),被代理的值在Promise对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的promise对象
常用场景

如果遇到接口的调用参数依赖于上一个接口的返回值,我们一般会这么写promise。

function getApi(params) {
  return new Promise((resolve) => {
    // 模拟ajax
    setTimeout(() => {
      resolve('api result: ' + params)
    }, 1000)
  })
}

getApi('start').then((res) => {
  getApi(res).then((res) => {
    getApi(res).then((res) => {
      console.log('finish', res)
    })
  })
})

promise的出现让异步方法可以像同步方法那样返回值,但是并没有解决回调地狱的问题,如上面的场景,接下来就该Generator出场了。

Generator

es6新增了一种声明方式,function *

function* 这种声明方式(function关键字后跟一个星号)会定义一个生成器函数(generator function),它返回一个  Generator  对象。

生成器函数在执行时能暂停,后面又能从暂停处继续执行。

调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的迭代器 ( iterator)对象。当这个迭代器的 next() 方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield的位置为止,yield后紧跟迭代器要返回的值。或者如果用的是yield*(多了个星号),则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。

next()方法返回一个对象,这个对象包含两个属性:value 和 done,value 属性表示本次 yield 表达式的返回值,done 属性为布尔类型,表示生成器后续是否还有yield语句,即生成器函数是否已经执行完毕并返回。

调用 next()方法时,如果传入了参数,那么这个参数会传给上一条执行的 yield语句左边的变量

运用生成器我们就可以这样去改造上面的例子:
用生成器函数包裹我们需要处理的语句,在yield后面跟我们需要处理的promise函数,next()后会执行到下一个yield位置然后暂停当前生成器的执行,至于恢复的时机就是这个promise执行完成(fulfilled/rejected)的时候,这时再调用next(),继续执行生成器接下来的语句,这里我们再实现一个自动运行生成器的方法。

function getApi(params) {
  return new Promise((resolve) => {
    // 模拟ajax
    setTimeout(() => {
      resolve('api result: ' + params)
    }, 1000)
  })
}

function* gen(stage0) {
  console.log(stage0)
  let stage1 = yield getApi('startParams')
  console.log('stage1', stage1)
  let stage2 = yield getApi(stage1)
  console.log('stage2', stage2)
  let stage3 = yield getApi(stage2)
  console.log('stage3', stage3)
  return 'all Done!!'
}

function run(generator, v) {
  let { value, done } = generator.next(v)
  if (!done) {
    value.then((res) => {
      run(generator, res)
    })
  } else {
    console.log(value)
  }
}

run(gen('start'))

async/await

es2017的新语法,对上面例子的改造就变成了

function getApi(params) {
  return new Promise((resolve) => {
    // 模拟ajax
    setTimeout(() => {
      resolve('api result: ' + params)
    }, 1000)
  })
}

async function getAllApi() {
  let stage1 = await getApi('startParams')
  console.log('stage1', stage1)
  let stage2 = await getApi(stage1)
  console.log('stage2', stage2)
  let stage3 = await getApi(stage2)
  console.log('stage3', stage3)
  return 'all Done!!'
}

getAllApi()

所以说async/await就是generator + promise的语法糖,还自带auto run的buff


AwesomeHan
125 声望4 粉丝

引用和评论

0 条评论