上一篇介绍到Promise可以用来处理非同步行为,但始终在阅读性方面还是不是很优,今天要介绍的是基於Promise让非同步的语法结构类似同步语言 --- Async/await,还有一些额外的优点也会一并介绍。
在一个函数前面加async可以确保此函数返回的是promise,其他返回的值都会被包装成resolve:
async function test() {
return 10
}
test().then( res => console.log(res)) // 10
直接返回promise也是可以的:
async function test() {
return Promise.resolve(1)
}
test().then( res => console.log(res)) //1
首先await只能在async函数中运作,所以基本上async/await是一体的,不会单独出现,await会让JavaScript引擎等到promise完成(settle)且返回结果:
async function test() {
let result = await new Promise((resolve, reject) => {
setTimeout(() => resolve("成功!"),1000)
})
console.log(result);
}
test(); // 一秒後 "成功"
续用昨天文章中的函数来说明:
function ownPromise(count, time = 1000) {
return new Promise((resolve, reject) => {
setTimeout(() => {
count? resolve(`第${count}次成功!`) : reject("失败")
},time)
})
}
我们可以得到以下结论:
console.log("Start")
async function fetchData() {
const dataA = await ownPromise(1);
const dataB = await ownPromise(2);
console.log(dataA, dataB)
}
fetchData();
console.log("End!")
//
Start!
End!
第1次成功! 第2次成功!
其中fetchData其实一样是非同步的部分,但是透过await可以做到让async function内的非同步是以同步的方式依序执行。
我们一样用ownPromise来说明,promise可以透过chain的方式来做error handle,且一旦遇到错误会直接跳转到catch:
ownPromise(0).then( res => {
console.log(res);
return ownPromise(1);
}).then( res => {
console.log(res);
return ownPromise(2);
}).catch( err => {
console.log(err);
})
// 失败 ownPromise(0)失败直接跳转到catch
那async/await因为已经转为同步的形式,所以如果遇到error没有处理的话,後续的代码都没办法运行,async/await的error handle一样用try..catch来处理:
async function fetchData() {
try {
const dataA = await ownPromise(1);
const dataB = await ownPromise(0);
console.log(dataA, dataB)
} catch(err) {
console.log('catch error',err)
}
}
fetchData();
async/await因为让非同步变成同步的形式,所以可以跟JavaScript语法一起搭配使用。
for..loop会等到当前的回圈中的await有回应後,且执行完回圈所有代码後才会进入下一个回圈,所以非常适合用来依序发出request。
let arrayData = [
{count:1, time:1000},
{count:2, time:2000},
{count:3, time:3000},
{count:4, time:4000},
]
// 情况一
async function testForLoop() {
const resArray = [];
for(let i = 0; i < arrayData.length; i++) {
const item = arrayData[i]
resArray.push(ownPromise(item.count, item.time));
console.log(`${item.count}执行完毕`)
}
console.log(resArray)
}
testForLoop();
// 情况二
async function testForLoop() {
const resArray = [];
for(let i = 0; i < arrayData.length; i++) {
const item = arrayData[i]
resArray.push(await ownPromise(item.count, item.time));
console.log(`${item.count}执行完毕`)
}
console.log(resArray)
}
testForLoop();
forEach的概念是每个item依序执行callback function,但是一旦开始执行後就马上接着换下一个item,所以会几乎同时执行每个回圈内容。
let arrayData = [
{count:1, time:1000},
{count:2, time:2000},
{count:3, time:3000},
{count:4, time:4000},
]
// 情况一
async function testForEach() {
const resArray = [];
arrayData.forEach(item => {
resArray.push(ownPromise(item.count, item.time))
console.log(`第${item.count}次执行完毕!`)
})
console.log(resArray);
for(const res of resArray) {
console.log(await res)
}
}
testForEach();
// 情况二
async function testForEach() {
const resArray = [];
arrayData.forEach(async item => {
resArray.push(await ownPromise(item.count, item.time))
console.log(`第${item.count}次执行完毕!`)
})
console.log(resArray);
}
testForEach();
与forEach类似,也是几乎同时执行,但是会马上执行return的动作,会无视async/await直接return。
let arrayData = [
{count:1, time:1000},
{count:2, time:2000},
{count:3, time:3000},
{count:4, time:4000},
]
// 情况一
async function testMap() {
let resArray = arrayData.map(item => {
return ownPromise(item.count, item.time)
})
console.log(resArray);
for(const res of resArray) {
console.log(await res)
}
}
testMap();
// 情况二
async function testMap() {
let resArray = arrayData.map(async item => {
return await ownPromise(item.count, item.time)
})
console.log(resArray);
for(const res of resArray) {
console.log(await res)
}
}
testMap();
所以情况一与二的结果是一样的:
前言 为什麽要把 debug 拿出来说呢? 我发现其实 debug 的流程比较少人讨论, 一般我们会...
Use Actual Cisco 350-701 Dumps to Learn Faster Pas...
: 听说你ARM很厉害 你怎麽学习的? 学习? 每天伏地挺身100下就好了阿 : ??? 在进入正题...
新零售行销模式案例,全通路时代来临该如何布局,一直以来都在担任辅导顾问为中小企业解决网路行销问题但都...
近年来 ROS (Robot Operating System,机器人作业系统) 目前已成熟应用於智...