🛩 Promise 的 async 和 await
🔗 相关链接 :
- async 函数 - JavaScript | MDN (mozilla.org) (opens new window)
- await - JavaScript | MDN (mozilla.org) (opens new window)
简而言之, async
/ await
的使用是 更加舒适使用 Promise 的方式。
# async
函数
- 返回值为 Promise 对象
- Promise 对象的结果由
async
函数执行的返回值决定。
(注:与 .then
相似)
使用 async
「修饰」的函数表示:这个函数总是返回一个 Promise ,其他值将自动被包装在一个 resolved
的 promise 中。
🌰 例子:
async function main(){
// 返回值为非promise
// return 123 // 成功的promise
// 返回的是promise对象
/*return new Promise((resolve, reject)=>{
resolve('ok') // 结果由这个结果决定
})*/
throw "error"
}
let result = main()
console.log(result)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# await
表达式
async function func() {
let value = await promise;
}
1
2
3
2
3
await
右侧的表达式一般为 Promise 对象,但也可以是其它的值。- 如果表达式为 Promise 对象,await 返回的是 Promise 成功的值。
- 如果表达式是其他值,直接将此值作为
await
的返回值。
关键字 await
让 JavaScript 引擎等待直到 promise 完成并返回结果。
注意:
await
必须写在async
函数中,但async
函数中可以没有await
。(await
写在普通函数中会报错)- 如果
await
的 Promise 失败了,就会抛出异常,需要通过try … catch …
捕获处理。
提示
await
实际上会暂停函数的执行,直到 promise 状态变为 settled,然后以 promise 的结果继续执行。这个行为不会耗费任何 CPU 资源,因为 JavaScript 引擎可以同时处理其他任务:执行其他脚本,处理事件等。
相比于 promise.then
,它只是获取 promise 的结果的一个更优雅的语法。并且也更易于读写。
🌰 例子:
async function main(){
let p = new Promise((resolve, reject)=>{
// resolve('ok')
reject('error')
})
// let result = await p; // 右侧为promise的情况
// console.log(result);
// let result2 = await 123; // 右侧为其他类型
// console.log(result2);
try {
let result3 = await p; // 右侧为promise失败
} catch (e) {
console.warn(e) // 获取到失败的结果
}
}
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
提示
async
/ await
可以与 Promis.all
结合使用:当需要同时等待多个 promise 时,可以使用 Promise
包装起来,然后使用 await
:
let results = await Promise.all([
fetch(url1),
fetch(url2),
...
]);
1
2
3
4
5
2
3
4
5
如果出现 error,也会正常传递,从失败了的 promise 传到
Promise.all
,然后变成能通过使用try..catch
在调用周围捕获到的异常。
# async
与 await
结合
🌰 例子(读取文件):
const fs = require('fs')
const util = require('util')
const mineReadFile = util.promisify(fs.readFile)
// 使用async与await
async function main() {
try {
let data1 = await mineReadFile('./resource/1.html')
let data2 = await mineReadFile('./resource/2.html')
let data3 = await mineReadFile('./resource/3.html')
console.log(data1 + data2 + data3)
} catch (err) {
console.warn(err)
}
}
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 相比于使用回调函数实现,减少写抛出异常
try-catch
结构。 - 在
async
与await
结合后,少用回调函数。
🌰 例子(发送 AJAX 请求):
<button id="btn">获取</button>
<script>
function sendAJAX(url) {
return new Promise((resolve, reject)=>{
const xhr = new XMLHttpRequest();
xhr.open('GET', url)
xhr.send();
xhr.onreadystatechange = function () {
if(xhr.readyState === 4) {
if(xhr.status >= 200 && xhr.status < 300) {
// 成功请求
resolve(xhr.response)
} else {
// 失败请求
reject(xhr.status)
}
}
}
})
}
let btn = document.querySelector("#btn")
btn.addEventListener('click', async function(){
let text = await sendAJAX('https://api.apiopen.top/getJoke')
console.log(text)
})
</script>
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
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
# 总结
async
关键字对函数的作用:- 让这个函数总是返回一个 promise。
- 允许在该函数内使用
await
。
Promise 前的关键字
await
使 JavaScript 引擎等待该 promise 确定状态,然后:- 如果有 error,就会抛出异常 ,就像那里调用了
throw error
一样。 - 否则,就返回结果。
- 如果有 error,就会抛出异常 ,就像那里调用了
编辑 (opens new window)
📢 上次更新: 2022/09/02, 10:18:16