JavaScript 异步函数 async await 介绍

TRAVELLERS DESERT
TRAVELLERS DESERT

对于异步处理JavaScript从未如此简单。有一段时间,我们使用了回调。然后,我们使用了承诺。现在,我们使用async…await。接下来我把这种方式代称为异步函数

异步功能

异步函数包含async关键字。您可以在正常的函数声明中使用它:

1
2
3
async function functionName(arguments){ 
//做一些异步的事情
}

您也可以在箭头功能中使用它。

1
2
3
const functionName = async(arguments)=> { 
//做一些异步的事情
}

异步函数总是返回promise

1
2
3
4
5
const getOne = async _ => { 
return 1
}
const promise = getOne()
promise.toString() //"[object Promise]"

await关键字

await 用于处理处理等待返回的结果,如下图所示

1
2
3
4
5
6
7
const getOne = async () => { 
return 1
}
getOne().then(
value => {
console.log(value)// 1
})

该await关键字可以等待解决的promise。一旦解决了promise,它就会返回传递给then调用的参数。

1
2
3
4
const test = async _ => { 
const one = await getOne()
console.log(one)// 1
}

处理错误

如果一个promise会导致错误,你可以通过catch调用来处理它,如下所示:

1
2
3
4
5
6
const getOne = async(success = true)=> { 
if(success)return 1
throw new Error('Failure!')
}
getOne(false)
.catch(error => console.log(error))//失败!

如果要在异步函数中处理错误,则需要使用try/catch。

1
2
3
4
5
6
7
8
const test = async () => { 
try {
const one = await getOne(false)
} catch(error){
console.log(error)//失败!
}
}
test()

如果您有多个await关键字,错误处理可能会使代码变得混乱……

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const test = async () => { 
try {
const one = await getOne(false)
} catch(error){
console.log(error)//失败!
}
try {
const two = await getTwo(false)
} catch(error){
console.log(error)//失败!
}
try {
const three = await getThree(false)
} catch(error){
console.log(error)//失败!
}
}
test()

还有更好的方法。一个总的catch函数

1
2
3
4
5
6
7
const test = async () => { 
const one = await getOne(false)
const two = await getTwo(false)
const three = await getThree(false)
}
test().
catch(error => console.log(error)))

注意:Promise catch方法仅允许您捕获一个错误。

多个await

await阻止JavaScript执行下一行代码,直到promise解析完成为止。这可能会导致代码执行速度减慢的意外后果。

为了显示这一点,我们模拟一个promise,创建一个延迟。我们可以创建一个延迟sleep函数。

1
2
3
const sleep = ms => { 
return new Promise(resolve => setTimeout(resolve,ms))
}

ms是解析前等待的毫秒数。如果您传递1000进入sleep,JavaScript的将等待一秒钟之后解决的Promise。

1
2
3
4
5
let promiseFun = async()=>{
console.time('now')
let slp = await sleep(1000) // 延时1秒
console.timeEnd('now') // 1000.106 ms
}

用async封装原生ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//async 
const Ajax = ({
method = 'get',
url = '/',
data,
async = true
}) => {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
let res = JSON.parse(xhr.responseText)
resolve(res)
}
}
xhr.open(method, url, async)
if (method === 'get') {
xhr.send()
}
if (method === 'post') {
let type = typeof data
let header
if (type === 'string') {
header = 'application/x-www-form-urlencoded'
}
else {
header = 'application/json'
data = JSON.stringify(data)
}
xhr.setRequestHeader('Content-type', header)
xhr.send(data)
}
})

}

Ajax.get = (url) => {
return Ajax({url})
}


async function use() {
let data = await Ajax.get('http://localhost:3000/getData')
console.log(data)
}

use()

小伙伴们也可以用async await 试着封装一下fetch。