必须知道的 Promise 进阶点(二)

很久没写博客了,今天终于把拖了很久的一篇写完了。git

原文地址:必须知道的 Promise 进阶点(二)github

前面还有:必须知道的 Promise 进阶点(一)web

async/await 基础

比起回调函数那看不懂的嵌套,Promise 要清爽很多,但当任务较多时, Promise 也有可能会有比较长的链和嵌套,这时候使用 async/await 就会让代码易读不少。异步

async

async 函数能够看做是 Promise 的语法糖:async

// resolve 状态
async function foo() {
    console.log('start')
    return 'resolve'
}
foo().then(data => {
    console.log('data:', data)
})
console.log('end')
// start
// end
// data: resolve


// reject状态
async function foo() {
    console.log('start')
    throw new Error('reject')
}
foo().catch(data => {
    console.log('data:', data.message)
})
console.log('end')
// start
// end
// data: reject
复制代码

与下面直接使用 Promise 方式书写的效果如出一辙:函数

// resolve 状态
function foo() {
    return new Promise((resolve, reject) => {
        console.log('start')
        resolve('resolve')
    })
}
foo().then(data => {
    console.log('data:', data)
})
console.log('end')
// start
// end
// data: resolve


// reject状态
function foo() {
    return new Promise((resolve, reject) => {
        console.log('start')
	reject('reject')
    })
}
foo().catch(data => {
    console.log('data:', data)
})
console.log('end')
// start
// end
// data: reject
复制代码

await

await 与其字面意思同样——等待,等待其后的函数执行完毕。ui

// resolve状态
async function foo() {
    console.log('start')
    return 'resolve'
}
async function bar() {
    const data = await foo()
    console.log('data', data)
}
bar()
console.log('end')
// start
// end
// data resolve

// reject状态
async function foo() {
    console.log('start')
    throw new Error('reject')
}
async function bar() {
    try {
        const data = await foo()
        console.log('data', data)
    } catch (err) {
	console.log('data', err.message)
    }
}
bar()
console.log('end')
// start
// end
// data reject
复制代码

await 只能在 async 函数里使用,不然会报错spa

循环中的 async/await

首先思考下面两个场景:code

  1. 有一个异步请求,须要屡次而且按顺序发送队列

  2. 有一个异步请求,须要屡次发送,但不用按顺序

场景一

同一个请求,屡次,按顺序。这就是一个典型的串行处理

function mockServer(i) {
    return new Promise((reslove, rejecy)=> {
        setTimeout(() => {
	    reslove('有值了:' + i)
        }, 1000 * i)
    })
}

async function getData(time) {
    var data = await mockServer(time)
    return data
}

var arr = [1,2,3,4]

async function showData() {
  console.time('showData')

  for (const item of arr) {
    const data = await getData(item)
    console.log(data)
  }
  console.timeEnd('showData')
}
showData()

// 有值了: 1
// 有值了: 2
// 有值了: 3
// 有值了: 4
// howData: 13100.510009765625ms
复制代码

咱们经过 for-of 循环调用了 4 次异步函数 getData,因为 getData 前面加了关键字 await,因此会依次排队处理,一共花了13秒多的时间。

场景二

同一个请求,屡次,不按顺序。这就是一个典型的并行处理,每一个请求同时发送,而不用排队等候,节约时间。

function mockServer(i) {
    return new Promise((reslove, rejecy)=> {
        setTimeout(() => {
	    reslove('有值了:', i)
        }, 1000 * i)
    })
}

async function getData(time) {
    var data = await mockServer(time)
    return data
}

var arr = [1,2,3,4]

async function showData() {
  console.time('showData')

  var allAsyncRequest = arr.map(item => getData(item))
  for await  (const asyncRequest of allAsyncRequest) {
    const data = asyncRequest
    console.log(data)
  }
  console.timeEnd('showData')
}
showData()

// 有值了: 1
// 有值了: 2
// 有值了: 3
// 有值了: 4
// showData: 4131.318115234375ms
复制代码

咱们在 map 的回调里调用了 4 次异步请求函数,将请求事件放到事件队列里面,让 4 个请求能够同时处理,而不影响后续任务的执行。

而后再经过 for await...of 来等待 4 个异步请求都执行完,一共花了 4 秒,大大节约了时间。

这里的 for await...of 还能够换一种写法:

for (const asyncRequest of allAsyncRequest) {
    const data = await asyncRequest
    console.log(data)
}
复制代码

也可使用 Promise.all()

Promise.all(allAsyncRequest).then((data) => {
    console.log(data)
    console.timeEnd('showData')
})

// ["有值了:1", "有值了:2", "有值了:3", "有值了:4"]
// showData: 4441.679931640625ms
复制代码

注意:这里不能使用 forEach 来进行循环处理,具体缘由能够看 当async/await赶上forEach,这篇文章已经写的很清楚了。

最后

学会熟练使用 async/await,能够很好提高代码的可阅读和可维护性,你们若是还有更好的用法和建议,欢迎在评论区补充。

相关文章
相关标签/搜索