除了Promise
之外,还有async/await
语法来处理非同步程序,它背後的操作原理与Promise
是一样的,所以也被称为Promise
的语法糖,它可以把Promise
写得更直觉和简洁(但其实也是见人见智)。
这篇文篇会整理以下知识:
async
函式、await
Promise
与async/await
写法async/await
抓远端资料async
要写在function
前面:
async function func() {
return 10;
}
func() //Promise {<fulfilled>: 10}
async
函式一定会回传一个Promise
物件,即使例子中的func
不是一个Promise
物件,它也会被包装成Promise
物件。
await
一定要写在async
函式里,否则会报错。所以写await
时,就要一并写async
。
await
工作还未完成,就不会跑後面的程序码在async
函式里,一定会等await
的工作完成,才继续跑该await
後面的程序。这样的写法使程序码看起来更像同步执行(同步即是「做完一件事才接着做下一件事」)。
第一个例子:
async function func(){
const p = await new Promise( (resolve,reject) =>
window.setTimeout( () => resolve(100),1000) )
console.log('跑完p才跑我') //跑完p才跑我
console.log(p) //100
}
func()
以上例子可见,在async
函里const p = ...
之後的程序码,需要等const p = ...
跑完才会被执行。
第二个例子:
用setTimeout
延迟计算,完成以下的事(要做完1才可做2)。
//把num1和num2相加
function add(num1,num2){
return new Promise( (resolve, reject) => {
window.setTimeout( () => {
resolve( console.log(num1 + num2) );
},1000)
})
}
//以下看起来像同步执行的感觉
async function func(){
//p1跑完,才跑p2
const p1 = await add(10,20); //30
const p2 = await add(30,40); //70
}
func()
当我们要执行多次非同步程序时,async/await的写法会更易阅读。以下例子是先把数字1放到func
里乘以10,之後把每次回传结果乘以10。我们用此例子来模拟执行多次非同步程序时的情况。
如果用async/await
去写:
function func(num){
return new Promise( (resolve, reject) => {
resolve(num * 10)
})
}
async function results(){
const result1 = await func(1);
console.log(result1); //10
const result2 = await func(result1);
console.log(result2); //100
const result3 = await func(result2);
console.log(result3); //1000
}
results()
如果用Promise
去写:
function func(num){
return new Promise( (resolve, reject) => {
resolve( num * 10)
})
}
func(1)
.then( success => {
console.log(success); //10
return(func(success));
})
.then( success => {
console.log(success); //100
return(func(success));
})
.then( success => {
console.log(success); //1000
})
比较两种写法,async/await
的写法里,因为用了await
,让人一看就知道这里会处理一个非同步程序,而且要等它完成才会跑下面的程序。所以async/await
的写法会更易阅读。
catch
处理错误情况如果前一个await
出错,那麽後面的程序就不会跑了:
function add(num1,num2){
return new Promise( (resolve, reject) => {
window.setTimeout( () => {
reject( num1 + num2 ); //在这里改成reject,模拟出错
},1000)
})
}
async function func(){
const p1 = await add(10,20);
const p2 = await add(30,40);
return `第一次相加结果:${p1},第二次相加结果:${p2}` //Uncaught (in promise) 30
}
func()
这时候async
函式会报错:Uncaught (in promise) 30
。
刚才提及过,async
本身会回传Promise
物件,所以我们可以像平时一样,用then
和catch
方法来抽取Promise
物件里的失败/成功值。这里我们用catch
来处理错误情况:
function add(num1,num2){
return new Promise( (resolve, reject) => {
window.setTimeout( () => {
reject( num1 + num2 ); //在这里改成reject,模拟出错
},1000)
})
}
async function func(){
const p1 = await add(10,20);
const p2 = await add(30,40);
return `第一次相加结果:${p1},第二次相加结果:${p2}`
}
func()
.then( success => {
console.log(`成功!`,success)
})
.catch( error => {
console.log(`错误!`,`最後相加结果:${error}`) //错误! 最後相加结果:30
})
try...catch
处理错误情况除了then
和catch
这个组合,另一个方法是用try
和catch
的语法去处理。直接在async
函式里写就可以了:
function add(num1,num2){
return new Promise( (resolve, reject) => {
window.setTimeout( () => {
reject( num1 + num2 ); //在这里改成reject,模拟出错
},1000)
})
}
async function func(){
try{
const p1 = await add(10,20);
const p2 = await add(30,40);
console.log(`第一次相加结果:${p1},第二次相加结果:${p2}`)
} catch(error){
console.log(`错误!`,`最後相加结果:${error}`) //错误! 最後相加结果:30
}
}
func()
try...catch
用法题外话,try...catch
是一个针对错误处理的语法,原理跟Promise
里的then
和catch
一样,只要出现错误,就会跳去跑catch
里的程序。catch(...)
里的err
的名称是可以自订的。当try
里面的程序出现错误,JavaScript会把错误原因放到catch(...)
里的参数中,即是err
。
try {
// code...
} catch (err) { // err是try区块里程序出错的原因
// error handling
}
另外,catch
後面的参数可以不写,这样就不会回传错误原因给你。例如以下范例(参考自这里),因为在JSON.parse(JSONdata)
出错,所以会执行catch
里的程序:
let JSONdata = {'错误JSON格式': 123123};
try{
//JSONdata的格式不合乎JSON的格式,所以JSON.parse会出错
let data = JSON.parse(JSONdata);
console.log(data);
}catch{
console.log('JSON资料格式错误!') //'JSON资料格式错误!'
}
async/await
抓远端资料最常处理非同步程序就是抓远端资料的情况了。以下例子用async/await
和XMLHttpRequest
来抓远端资料,并且用try...catch
来处理成功或错误结果:
let getJSON = url => {
return new Promise( (resolve,reject) => {
let xhr = new XMLHttpRequest();
xhr.open('get',url);
xhr.send(null);
xhr.onload = () => {
if(xhr.status === 200){
resolve(JSON.parse(xhr.responseText));
}else{
reject(new Error(xhr.statusText));
}
}
})
}
//直接在async函式里,用try...catch处理成功或失败的结果
async function printJSON(url){
try{
const data = await getJSON(url);
console.log(data); //显示回传资料 {results: Array(1), info: {…}}
}catch(error){
console.log('错误!',error);
}
}
printJSON('https://randomuser.me/api/')
async/await
是Promise
的语法糖,背後运作原理与Promise
是一样,作用是把Promise
写得更易读async
要写在function
前面async
函式一定会回传一个Promise
物件await
要放在async
函式里面async/await
的错误处理方法:
catch
方法(就如平时写Promise
一样)try...catch
方法JS 原力觉醒 Day16 - Async / Await:Promise 语法糖
JAVASCRIPT.INFO - Async/await
铁人赛:JavaScript Await 与 Async
告别 JavaScript 的 Promise!迎接 Async/Await 的到来
JAVASCRIPT.INFO - Error handling, "try..catch"
<<: Day 28: Divide and Conquer
首先我们需要有 Docker 环境,如果还没有可以参考 Docker 安装 制作 Dockerfil...
金鱼都能懂的网页切版:26、27 版面组合 https://codepen.io/mikeyam/p...
先前的GraphQL(Hasura)-Webhook身份验证有介绍到可以使用Webhook做身份级别...
开始绘制维修单派工关联表,画错蛮多次。我学习的方式,先在网路上找相关的图参考,思考後进行绘制动作。画...
线上 Ruby 编辑器:https://runrb.io/ Ruby String 文件:http...