1.async 函数 & await
1.1. async含义
ES2017 标准引入了 async 函数,使得异步操作变得更加方便。
async 函数是 Generator 函数的语法糖。
什么是语法糖?
意指那些没有给计算机语言添加新功能,而只是对人类来说更“甜蜜”的语法。语法糖往往给程序员提供了更实用的编码方式,有益于更好的编码风格,更易读。不过其并没有给语言添加什么新东西。反向还有语法盐:
主要目的是通过反人类的语法,让你更痛苦的写代码,虽然同样能达到避免代码书写错误的效果,但是编程效率很低,毕竟提高了语法学习门槛,让人齁到忧伤。。。
1.2. async的使用
async函数使用时就是将 Generator 函数的星号(*)替换成async,将yield替换成await,仅此而已。
//创建异步函数
async function show() {
let result =await 20;
console.log(result);
}
show()
async function show (){
await '33'
}
let p1 = show();
1.2.1 await配合async使用
async function fn(){ // async 表示异步,这个函数里面有异步的任务
let result = await xxxx; // 表示等待await后面的结果需要等待,等出来在处理
}
1.3. async函数对 Generator 函数的区别:
(1)内置执行器。
Generator 函数的执行必须靠执行器,而async函数自带执行器。也就是说,async函数的执行,与普通函数一模一样,只要一行。
(2)更好的语义。
async和await,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。
(3)正常情况下,await命令后面是一个 Promise 对象。如果不是,会被转成一个立即resolve的 Promise 对象。
(4)返回值是 Promise。
async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。
进一步说,async函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而await命令就是内部then命令的语法糖。
async function show() {
let result =await new Promise((res)=>{ //后面跟Promise,里面定义一个回调函数。await会始终等到后面的Promise调用then方法,把then方法的值取出来赋值给result
setTimeout(()=>{
res(50)
},3000)
});
console.log(result);
}
show()
async function show() {
let result = await new Promise((res) => { //后面跟Promise,里面定义一个回调函数。await会始终等到后面的Promise调用then方法,把then方法的值取出来赋值给result
setTimeout(() => {
res(50)
}, 3000)
});
console.log(result);
return result + 20;
}
show()
let res = show();
console.log(res);
res.then((data) => { console.log(data); })
1.4. async 的特点
- await 只能放到async函数中使用
- 相比generator 语义化更强
- await后面可以是promise对象,也可以是数字,字符串,布尔值
- async 函数返回的是一个promise对象
- 只要await 语句后面的Promise的状态变成reject,那么整个async函数会中断执行
1.4.1 验证async函数返回一个promise对象
async function fn(){
}
console.log(fn()); //Promise
// 使用
async function fn(){
return 'welcome';
}
fn().then(res => {
console.log(res); // welcome
})
1.4.2 如果async函数中出错
async function fn(){
throw new Error('Error 出错了')
}
fn().then(res => {
console.log(res);
}).catch(err => {
console.log(err); // Error 出错了
})
async function show() {
throw new Error('Error 出错了')
}
let res = show();
console.log(res);
res.then((data) => { console.log(data); })
.catch(err => {
console.log(err); // Error 出错了
})
async function show() {
try {
throw new Error('Error 出错了')
let result = await 20;
console.log(result);
} catch (err) {
console.log(err)
}
}
let promise = show()
promise.then((data) => console.log(data))
1.4.3 如果await后面的语句出错,函数后面将中断执行
错误在成功之后,错误和成功都会执行
async function fn(){
let a = await Promise.resolve("成功了");
console.log(a);
await Promise.reject('出错了') //await 后面如果是失败状态promise 这条语句后面的代码都不会执行
}
fn().then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
// 打印结果
// 成功了
// 出错了
但是如果错误在前,成功将不会执行
async function fn(){
await Promise.reject('出错了')
let a = await Promise.resolve("成功了");
console.log(a);
}
fn().then(res => {
console.log(res);
}).catch(err => {
console.log(err);
})
// 打印结果
// 出错了
1.5. 解决async函数中的报错
如何解决async函数中抛出错误,影响后续代码执行;
这个问题比较严重,虽然是async的特点,但是我又不知道程序什么时候出错,所以我不希望出错的代码影响后续运行,导致程序中断
1.5.1使用 try { } catch (){}
async function fn(){
try{
await Promise.reject('出错了')
}catch(e){
let a = await Promise.resolve("成功了");
console.log(a);
}
}
1.5.2 添加catch 捕获错误
本来await后面的就是promise,那么我们就可以直接使用catch处理
async function fn(){
await Promise.reject('出错了').catch(err=>{
console.log(err);
})
let a = await Promise.resolve("成功了");
console.log(a);
}
其实跟网络打交道的都不保险,你不可能给每一个await后面的promise对象都加catch
1.5.3 统一捕获错误
个人建议,只要有await的地方都try catch掉 然后统一处理结果
try {
let f1 = await Promise.resolve('成功了');
let f2 = await Promise.resolve('成功了');
let f3 = await Promise.reject('出错了');
}catch(e){}
1.5.4 也可以是用Promise.all()方法
如果你多次请求的数据之间没有关联,就可以使用Promise.all()
// async
async function fn(){
let [f1,f2,f3] = await Promise.all([
Promise.resolve('成功了1'),
Promise.resolve('成功了2'),
Promise.resolve('成功了3')
])
console.log(f1);
console.log(f2);
console.log(f3);
}
fn();
同时配合解构处理
例子:
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<script>
async function show() {
let p1 = await new Promise((res, rej) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/1',
success: function (data) {
console.log(data);
res()
},
error: function (err) {
rej()
}
})
});
let p2 = await new Promise((res, rej) => {
$.ajax({
url: 'https://jsonplaceholder.typicode.com/todos/2',
success: function (data) {
console.log(data);
res()
},
error: function (err) {
rej()
}
})
});
}
let pp = show();
generator只是一个过渡期,强烈建议大家用async就可以了
网友评论