JavaScript中的async/await是AsyncFunction特性中的关键字。(读者可自行查阅改链接中内容)
async定义的异步函数,通过使用 await,让异步函数的表现更像是同步函数。不用再层层回调。它是Generator函数的语法糖。其中async来声明该函数里有异步操作。await表示紧跟在后面的表达式需要等待结果
与Generator函数比优点:
- 内置执行器。
Generator函数的执行必须依靠执行器,而Aysnc函数自带执行器,调用方式跟普通函数的调用一样‘ - 更好的语义。
async和await相较于*和yield更加语义化 - 更广的适用性。
co 模块约定,yield命令后面只能是Thunk 函数或Promise对象。而async函数的await命令后面则可以是Promise或者 原始类型的值(Number,string,boolean,但这时等同于同步操作) - 返回值是
Promise。async函数返回值是Promise 对象,比Generator函数返回的Iterator 对象方便,可以直接使用then()方法进行调用
如果你还不了解Generator函数,你可以查阅下面:
先看几个demo:
1、之前不用async的异步Promise操作
定义个获取用户信息的函数:
function getUserInfo() {
return new Promise((resolve, reject) => {
fetch('http://abc.com')
.then(res => {
reslove(res)
}, error => {
reject(error)
})
})
}
function showUserInfo() {
getUserInfo()
.then(res => {
//...
}, error => {
//....
})
}
2、使用Generator 方式
function* showUserInfo() {
const user = yield getUserInfo()
return user
}
const g = showUserInfo()
cosnt res = g.next().value()
result.then(res => {
//..
}, error => {
//..
})
Generator的方式解决了 Promise的一些问题,流程更加直观、语义化。但是 Generator的问题在于,函数的执行需要依靠执行器,每次都需要通过 g.next()的方式去执行。
3、使用async/await
async function showUserInfo() {
const res = await getUserInfo();
return res
}
showUserInfo().
then(res => {
//..
})
看到这里你可能还有点一脸懵逼,别着急,接着往下看。
4、语法
async函数内部返回一个Promise对象。其在内部返回(return)的值会成为then方法的参数。
async function f() {
return 'hello world'
};
f().then( (v) => console.log(v)) // hello world
如果async函数内部抛出异常,则返回的Promise状态会变为reject状态。抛出的错误会被catch方法捕捉到。
async function e(){
throw new Error('error');
}
e().then(v => console.log(v))
.catch( e => console.log(e));
需要注意的是:async返回的Promise对象,必须等到内部所有的await命令的Promise对象执行完毕,才会发生状态改变。也就是说只有当async内部的异步操作都成功执行完,才会执行then里的方法
const delay = timeout => new Promise(resolve=> setTimeout(resolve, timeout));
async function f(){
await delay(1000);
await delay(2000);
await delay(3000);
return 'done';
}
f().then(v => console.log(v)); // 等待6s后才输出 'done'
正常情况下,await命令后面是一个 Promise对象,返回该对象的结果。如果不是 Promise对象,就直接返回对应的值(如果没有返回值,那么默认返回值将是undefined)
async function f() {
return await 1
};
f().then( (v) => console.log(v)) // 1
如果此时返回的 reject的状态,就会被catch捕获。
async function foo() {
return Promise.reject(123)
}
foo().then().catch(e => console.log(e)) //控制台打印出 '123'
5、async函数的错误处理
let a;
async function f() {
await Promise.reject('error');
a = await 1; // 这段 await 并没有执行
}
f().then(v => console.log(a)).catch(err => console.log(err))
只要async函数中的一个 await出现reject状态,那么后面的await就不会再执行。
此时错误处理使用try/catch来处理。
let a;
async functoin f() {
try {
await Promise.reject('error')
} catch (err) {
console.log(err)
}
a = await 1;
return a
}
f().then(v => console.log(a)).catch(err => console.log(err))
如果有多个await,可以都放在try/catch中。
6、一些代码来加强认知
async function asyncFun() {
return '我后执行'
}
asyncFun().then(v => console.log(v))
console.log('我先执行');
这段代码会先打印出我先执行,再打印我后执行.
因为声明了asyncFun为异步函数。该函数虽然先执行了,但是不会阻断后面代码的执行。同步代码先执行。
注意对比下面代码,理解执行顺序。
const timeOut = timeOut => {
return new Promise(resolve => setTimeout(resolve, timeOut))
}
async function timeFun() {
await timeOut(1000)
await timeOut(2000)
return 'end..'
}
timeFun().then(v => console.log(v))
//打印结果
[Running] node "c:\lhch\work\Projects\own\vue\async.js"
end..
[Done] exited with code=0 in 3.093 seconds
//可以看出 在3s后打印出了end.. ,这是使用了await的效果
7、async里的函数必须将结果return
async里必须将结果return,如果不返回结果,那么不管是resolve或者reject状态,其值都是undefined。这里建议使用箭头函数。
这是正确的写法,控制台会打印errrrr
async function errFun() {
return Promise.reject('errrrr')
}
errFun().then().catch(v => console.log(v))
错误的写法:
async function errFun() {
Promise.reject('errrrr')
}
这里执行errFun控制台会直接报错。
需要深入理解的: 只要async返回的值不是异常或者reject,就会判定成功。在async函数里,可以return各种类型的值。
只有出现如下情况的时候,才会判定失败reject:
- 内部使用未声明的变量或者函数
- 内部直接抛出错误(
throw new Error)或者返回reject状态(retrun Promise.reject) - 函数方法执行出错
async function c() {
return '接受到了吧'
}
c().then(v => console.log(v))
上面代码控制台会打印出 '接受到了吧',同时显示://Promise { <resolved>: undefined }
为什么 resolved的是undefined呢,因为then后是执行的console语句,这里没有返回值。
一个小总结:
- 是一种编写异步代码的新方法。之前异步代码的方案是
callback和promise。 - 建立在
promise的基础上,与promise一样也是非阻塞的。 async/await让异步代码看起来、表现起来更像同步代码。这正是其魅力(作用)所在。
建议您读此文的时候,自己手敲代码,加深理解.
如果此文帮到了你,你可以捐赠,以示鼓励。


本文详细探讨了JavaScript中Async/Await特性的使用方法与优势,包括其如何简化异步编程,与Generator函数的区别,以及错误处理技巧。
715

被折叠的 条评论
为什么被折叠?



