Promise简介、promise.all与race应用

本人前端小白,项目经历较少,遇到页面接口请求较多时总会有些疑惑,不知道怎么处理合理。看之前的项目代码,写了不知多少回调,最近整理promise.all和async/await两个方法,分享一下。同时结合两者优化下接口性能,减少请求耗时。

Promise

众所周知,Promise 是一个对象,用于表示一个异步操作的最终完成 (或失败), 及其结果值。

语法:new Promise( (resolve, reject) => {...} /* executor */ );

let promise = new Promise((resolve,reject) => {
    resolve('success')
     // or
    reject('error')
})

该对象接收两个参数

  • resolve: 将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去.
  • reject: 将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
promise.then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
})

then方法会返回一个Promise,接收一个回调函数作参数,回调函数接受Promise对象传出的值作为参数

Promise.all()

将多个promise实例包装成一个新的promise实例,接收一个数组作参数。成功时返回一个数组,数组中包括所有子promise的结果;失败时,返回第一个失败promise的结果。

let p1 = new Promise((resolve,reject) => {
   resolve('success1')
   //reject('error')
})
let p2 = new Promise((resolve,reject) => {
    resolve('success2')
 })
 let p3 = new Promise((resolve,reject) => {
    reject('error')
 })

成功状态时:

Promise.all([p1,p2]).then(res => {
     console.log(res)
 }).catch(err => {
     console.log(err)
 })
 
 // 返回结果
 
 ['success1', 'success2' ]

失败时:

 Promise.all([p1,p2,p3]).then(res => {
     console.log(res)
 }).catch(err => {
     console.log(err)
 })
 
 // 输出
 error

注意:

  • 成功时返回数组中,值的顺序跟传入参数中promise实例的顺序对应,类似于同步执行,不会因为返回结果耗时的影响。

适用场景:

  • 页面请求过多时,可根据Promise.all()返回结果判断所有请求是否成功,否则使页面一直处于loading状态,避免用户操作,或者提是错误。
  • 发送多个请求,需要根据请求顺序获取和使用数据的场景。
  • 避免promise使用不合理或各种回调函数造成地狱回调,无法维护。

Promise.race()

用法同Promise.all(),哪个子promise结果先被返回,就返回该结果,不管是成功还是失败状态。

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  },1000)
})

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('error')
  }, 500)
})

Promise.race([p1, p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)  // 'error'
})

async/await

  • 见名知意: 异步与等待
  • 同步思维解决异步问题的方案。

async

函数使用async后将转换成Promise,并且其返回值也是一个Promise。

async function fn() {
    console.log('async')
    return 1
}
fn()

// 结果
async
Promise {: 1}

如果函数内部未使用return,resolved的值为undefind。(最好在浏览器上尝试,node上有返回promise,但无法显示,可能我的node4版本较低)

  • 既然返回值是Promise,那我们变可以使用then()获取。
async function fn() {
    console.log('async')
    return 1
}
fn().then(res => {
    console.log(res) // 1
})

await

  • await只能在async函数内部使用,用在普通函数里就会报错

结合实际开发来说明

fetch('https://blog.csdn.net/')
  .then(res => {
    console.log(res)
    return fetch('https://juejin.im/')
  })
  .then(res => {
    console.log(res)
  })
  .catch(error => {
    console.log(error)
  })
  • 这种代码可能大家都有见过,虽然能体现等待的效果,但当链式调用过多,将充斥着多个then,配合业务逻辑那就部那么语义化,且难以维护。
async function foo () {
  try {
    let response1 = await fetch('https://blog.csdn.net/')
    console.log(response1)
    let response2 = await fetch('https://juejin.im/')
    console.log(response2)
  } catch (err) {
    console.error(err)
  }
}
foo()

  • 上面代码,整个异步处理的逻辑都是使用同步代码的方式来实现的,感觉就在写同步代码,比较符合人的线性思维的。
  • await 后面一定是Promise 对象,如果不是会自动包装成Promise对象。

promise.all与async/await结合,优化请求

先看个栗子

function fn1() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p1')
        },1000)
    })
}
function fn2() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p2')
        },2000)
    })
}
async function fn() {
    let p1 = await fn1()
    let p2 = await fn2()
}
 
 fn()

忽略浏览器引擎的耗时,fn1,fn2理想总共耗时3000毫秒

function fn1() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p1')
        },1000)
    })
}
function fn2() {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve('p2')
        },2000)
    })
}

async function fn() {
    let [res1, res2] = await Promise.all([test1(), test2()])
}
fn()

而这种写发理想耗时2000ms,因为promise.all是将多个异步操作并行实现。
需要注意的是,多个await命令不存在依赖关系。

你可能感兴趣的:(Promise简介、promise.all与race应用)