潜入理解ES6-Promise用法小结

写在前面

感性上的理解:Promise咱们能够理解为作了一个保证,作了这个保证无论成功resolve()仍是失败reject()都会告知咱们———返回带有最终结果或者拒绝缘由 的Promisejavascript

Promise的三种状态

  • 挂起
  • 已成功
  • 已完成

其中后两种都是异步操做完成后的状态java

Promise作保证

Promise对象用于表示一个异步操做的最终状态(完成或失败),以及其返回的值。ios

MDN对Promise的定义如上,能够理解为此对象作了一些保证,告知咱们异步操做的状态。具体以下:axios

  • 当前事件队列执行完成以后,再调用回调函数
  • 回调函数是经过then添加的
  • 添加多个then,能够添加多个回调函数,依次执行

Promise链式调用

存在的需求:有时候咱们须要连续调用多个异步操做,每个操做都创建在获得上一部结果以后。之前有回调函数,这样会容易形成回调地狱。而采用Promise以后,每一步操做成功/失败以后都会带上其结果,执行下一个操做。api

// 回调地狱
doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
        console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);

//采用Promise链式调用以后
doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
复制代码

错误处理

在上面的代码段1中,有三个错误回调函数。而在Promise链式调用中,只在结尾加上错误处理回调便可,当有错误抛出时,会返回一个带有错误缘由的Promise到下一级catch,直到最底端catch函数。数组

// 依次输出: Initial Do that
new Promise((resolve, reject) => {
    console.log('Initial');
    resolve();
})
.then(() => {
    throw new Error('Something failed');
    console.log('Do this');
})
.then(() => {
    console.log('Do this whatever happened before');
})
.catch(() => {
    console.log('Do that');
})
复制代码

此外,若是中途捕获了异常,依然能够接着then下去:promise

/* * 依次输出: * Initial * Do that * Do this whatever happened before */
new Promise((resolve, reject) => {
    console.log('Initial');
    resolve();
})
.then(() => {
    throw new Error('Something failed');
    console.log('Do this');
})
.catch(() => {
    console.log('Do that');
})
.then(() => {
    console.log('Do this whatever happened before');
})
复制代码

缘由在于catch(failureCallback)自己是then(null, failureCallback)的缩略形式,也是返回带有当前状态的Promise。下面这样我们还能捕获到异常信息:app

/* * 依次输出: * Initial * Something failed * Do that * Do this whatever happened before */
new Promise((resolve, reject) => {
    console.log('Initial');
    resolve();
})
.then(() => {
    throw new Error('Something failed');
    console.log('Do this');
})
.catch((e) => {
    console.log(e.message)
    console.log('Do that');
})
.then(() => {
    console.log('Do this whatever happened before');
})
复制代码

使用async/await语法糖

一个栗子异步

// 使用Promise
doSth()
    .then(res => doSthElse(res))
    .then(newRes => doThirdTh(newRes))
    .then(finalRes => {
        console.log(`finalResult is ${finalRes}`)
    })
// 使用async/await将异步代码写成同步样式
async funtion foo () {
    let res = await doSth()
    let newRes = await doSthElse(res)
    let finalRes = await doThirdTh(newRes)
    console.log(`finalResult is ${finalRes}`)
}
复制代码

Promise.resolve()、Promise.reject()妙用

使用这两种静态方法能够建立resolve或reject的保证,栗子以下:async

getRecommend () {
    let today = new Date()
    let date = new Date(today.getFullYear(), today.getMonth() + 1, today.getDate(), 9)
    
    return axios.get(`/api/getRecommend?date=${Number(date)}`
    ).then(response => {
      return Promise.resolve(response.data)
    }).catch(err => {
      console.log(err)
    })
}
复制代码

当使用axios成功请求/api/getRecommend时,axios返回一个Promise对象,由于getRecommend()是要export出去的,这里直接返回一个状态完成的Promise,调用getRecommend()时,若是成功响应直接能够recommend.getRecommend().then(res => {})获取响应结果。

Promise.all()、Promise.race()并行执行多个Promise对象

  • Promise.all()是全部Promise对象状态都是‘已成功’才结束
  • Promise.race()是有一个Promise对象状态‘已成功’就结束

Promise串行执行

Promise链式调用

下面这个累加例子很好地显示了Promise之间传值计算:

// 第一步,执行XXX操做,保证了***结果
let step1 = function () {
  let val = 1
  console.log(`this is step1 , the value is ${val}`)
  // 拒绝的状况,balalala...
  if (val > 0){
    return Promise.resolve(val)
  }
  return Promise.reject(val)
}
// 第二步,执行XXX操做,保证了***结果
let step2 = function (val) {
  val += 1
  console.log(`this is step2 , the value is ${val}`)
  return Promise.resolve(val)
}
// 第三步,执行XXX操做,保证了***结果
let step3 = function (val) {
  val += 1
  console.log(`this is step3 , the value is ${val}`)
  return Promise.resolve(val)
}

step1().then((val)=>{
  return step2(val)
}).then((val)=>{
  return step3(val)
}).then((val)=>{
  console.log(`finally, the value is ${val}`)
})

// 输出结果
this is step1 , the value is 1
this is step2 , the value is 2
this is step3 , the value is 3
复制代码

aysnc/await

再用async/await语法糖实现一遍累加

// 在这里咱们把每一步操做看做异步的
function step21() {
  let val = 1
  console.log(`this is step1 , the value is ${val}`)
  return val
}

function step22(val) {
  val += 1
  console.log(`this is step2 , the value is ${val}`)
  return val
}

function step23(val) {
  val += 1
  console.log(`this is step3 , the value is ${val}`)
  return val
}

(async () => {
  // await使用必须在async函数内
  let val = await step21()
  val = await step22(val)
  val = await step23(val)
})()

// 输出结果
this is step1 , the value is 1
this is step2 , the value is 2
this is step3 , the value is 3
复制代码

Promise数组串行

使用数组的reduce()方法依次执行,

// 第一步,执行XXX操做,保证了***结果
let step1 = function () {
  let val = 1
  console.log(`this is step1 , the value is ${val}`)
  // 拒绝的状况,balalala...
  if (val > 0){
    return Promise.resolve(val)
  }
  return Promise.reject(val)
}
// 第二步,执行XXX操做,保证了***结果
let step2 = function (val) {
  val += 1
  console.log(`this is step2 , the value is ${val}`)
  return Promise.resolve(val)
}
// 第三步,执行XXX操做,保证了***结果
let step3 = function (val) {
  val += 1
  console.log(`this is step3 , the value is ${val}`)
  return Promise.resolve(val)
}

let steps = [step1, step2, step3]
steps.reduce((promise, fn, index)=>{
  console.log(index)
  return promise.then((val)=>{
    return fn(val)
  })
  // reduce函数init参数
}, Promise.resolve())

// 输出结果
this is step1 , the value is 1
this is step2 , the value is 2
this is step3 , the value is 3
复制代码

async/await数组串行

暂时只想到数组的方法,使用Array.prptotype.reduce()为解决,仍是没有深刻了解reduce()是如何实现的

async function foo () {
  let val
  for (let i = 0; i < steps.length; i++) {
    if (i===0) {
      val = await steps[i]()
    }else {
      val = await steps[i](val)
    }
  }
}
foo()
复制代码
相关文章
相关标签/搜索