当前位置:网站首页>Promise学习(四)异步编程的终极解决方案async + await:用同步的方式去写异步代码
Promise学习(四)异步编程的终极解决方案async + await:用同步的方式去写异步代码
2022-08-01 10:21:00 【對不起该用户已成仙】
目录
前言
1. async 函数
ES2017 标准引入了 async
函数,使得异步操作变得更加方便。 async
函数是使用 async
关键字声明的函数。 async
函数是AsyncFunction构造函数的实例, 并且其中允许使用 await
关键字。async
和 await
关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise。
async
是一个加在函数前的修饰符,被async
定义的函数会默认返回一个Promise对象resolve
的值。因此对async
函数可以直接then
,返回值就是then方法传入的函数。
- 函数的
返回值
为 promise 对象 - promise 对象的结果由
async
函数执行的返回值决定
async function main() {
//1. 如果返回值是一个非Promise类型的数据
// return 521; // 成功
//2. 如果返回的是一个Promise对象
// return new Promise((resolve, reject) => {
// // resolve('ok'); // 成功
// reject('err'); // 失败
// });
//3. 抛出异常
throw "失败了"; // 失败
};
let result = main();
console.log(result);
可以看出执行的结果由
async
函数的返回值状态来决定
2. await表达式
await
也是一个修饰符,只能放在async
定义的函数内。可以理解为等待
。await
后面可以跟任何的JS 表达式
。虽然说 await
可以等很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await
的是 promise对象会造成异步函数停止执行,并且等待 promise 的解决,如果等的是正常的表达式则立即执行
注意:
1.
await
可以理解为是async wait
的简写。await
必须出现在async
函数内部,不能单独使用。async
函数可以单独使用
2.await
主要是对Promise对象成功的结果获取
3. 如果await
的 promise 失败了, 就会抛出异常, 需要通过try...catch
捕获处理
await
右侧的表达式一般为 promise 对象, 但也可以是其它的值- 如果表达式是 promise 对象,
await
返回的是 promise 成功的值 - 如果表达式是其它值, 直接将此值作为
await
的返回值
成功状态:
const main = async () => {
let p = new Promise((resolve, reject) => {
resolve('ok');
});
// 1. 右侧为promise的情况
let res1 = await p;
console.log(res1); // ok
//2. 右侧为其他类型的数据
let res2 = await 20;
console.log(res2); // 20
}
main();
失败状态(try...catch
捕获处理):
const main = async () => {
let p = new Promise((resolve, reject) => {
reject('err了');
});
// 如果promise是失败的状态
try {
let res3 = await p;
} catch(reason) {
console.log(reason);
}
}
main();
3. 解决异步编程的终极方案 async + await
先说一下Promise中各个任务状态的理解:
- Promise==>异步
- await==>异步转同步
- async==>同步转异步
举一个回调地狱的异步例子:(回调地狱是指:多层嵌套函数,函数的返回值是下一个函数的执行条件。)
setTimeout(() => {
console.log('1');
setTimeout(() => {
console.log('2');
setTimeout(() => {
console.log('3');
}, 1000);
}, 2000);
}, 3000);
它会每隔一秒依次输出
'1'
,'2'
,'3'
,回调地狱的缺点是不便于阅读 不便于异常处理
解决方案:
- 原生Promise 链式调用的方式在前面的 Promise学习(一)Promise是什么?怎么用?回调地狱怎么解决?中有提到过,感兴趣的可以去看看哦!
- 终极方案 async + await
const test1 = n => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(n)
}, 1000);
});
}
const test = async () => {
console.log(await test1(1));
console.log(await test1(2));
console.log(await test1(3));
}
test();
这样做的
好处
是:结构清晰
,便于阅读
,方便异常处理
(如果抛出了异常,可以用try...catch
处理异常),这里为了方便理解,直接用的成功的状态。
4. async 和 await 结合实践1:读取文件信息
小案例1:读取 1.html 2.html 3.html 三个文件内容,有两种方法,一是回调函数
形式实现,二是 async
+ await
实现。
1. 回调函数形式:
// 引入fs模块
const fs = require('fs');
//回调函数的方式
fs.readFile('./resource/1.html', (err, data1) => {
if (err) throw error;
fs.readFile('./resource/2.html', (err, data2) => {
if (err) throw error;
fs.readFile('./resource/3.html', (err, data3) => {
if (err) throw error;
console.log(data1 + data2 + data3);
});
});
});
打开集成终端输入 node .\当前要运行的文件名
,即可以读取三个文件内容。
2.
async
+await
实现:
// 引入fs模块
const fs = require('fs');
//引入 util 模块
// util.promisify 方法可以将函数直接变成promise的封装方式,不用再去手动封装
const util = require('util');
const mineReadFile = util.promisify(fs.readFile);
//async 与 await 实现
const main = async () => {
try{
//读取第一个文件的内容
let data1 = await mineReadFile('./resource/1xxx.html'); // 错误文件
let data2 = await mineReadFile('./resource/2.html');
let data3 = await mineReadFile('./resource/3.html');
console.log(data1 + data2 + data3);
}catch(e){
console.log(e); // 错误会提示
console.log(e.code); // 错误中的一个属性
}
}
main();
如果文件名都是正确的会得到和回调函数形式实现的一样的结果,当我们输入错误的文件名时,最后可以得到
try...catch
处理的错误的相关信息
5. async 和 await 结合实践2:结合Ajax获取接口信息
小案例2:结合Ajax获取接口信息, async
+ await
实现。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<button id="btn">点击获取段子</button>
<script> const sendAJAX = url => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest(); xhr.responseType = 'json'; 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); } } } }) } $("#btn").click(async () => {
// 获取接口文字信息 let datas = await sendAJAX('https://pagead2.googlesyndication.com/getconfig/sodar?sv=200&tid=gda&tv=r20220718&st=env'); console.log(datas); }); </script>
</body>
</html>
注意接口的跨域问题
这里提一下
跨域问题
,因为不会自己写接口,网上找的接口很多都有跨域问题,所以我们在选择接口是要看清网络
中有无CORS错误
的字眼,跨域的接口是不能成功返回数据的。
至此,Promise学习篇暂时以完结,如果还有补充后续会继续更新,如果觉得对你有帮助的话请继续支持哦!
Authors: min
时间: 2022年7月27日
边栏推荐
- ModelArts-based object detection YOLOv3 practice [play with HUAWEI CLOUD]
- CTO strongly banning the use of the Calendar, that in what?
- Batch大小不一定是2的n次幂!ML资深学者最新结论
- SQL Server database schema and objects related knowledge notes
- DBPack SQL Tracing 功能及数据加密功能详解
- 对于小应用来讲,使用哪款数据库比较好?
- Google Earth Engine APP——15行代码搞定一个inspector高程监测APP
- notes....
- 世界第4疯狂的科学家,在103岁生日那天去世了
- 4种常见的鉴权方式及说明
猜你喜欢
Google Earth Engine APP——15行代码搞定一个inspector高程监测APP
C语言小游戏——扫雷
MacOS下postgresql(pgsql)数据库密码为什么不需要填写或可以乱填写
rpm and yum
Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (2) Mini Program Functions
50.【Application of dynamic two-dimensional array】
The use of scrapy crawler framework
WTM:ASP.NET Core快速开发利器!
CTFshow,命令执行:web32
ClickHouse入门介绍与其特性
随机推荐
How programmers learn open source projects, this article tells you
怎么找出电脑隐藏的软件(如何清理电脑隐藏软件)
退役划水
STM32 Personal Notes - Embedded C Language Optimization
阿里腾讯面试一二
我是如何保护 70000 ETH 并赢得 600 万漏洞赏金的
深度学习 | MATLAB实现一维卷积神经网络convolution1dLayer参数设定
CTO strongly banning the use of the Calendar, that in what?
浏览器快捷键大全
招聘随想2022
retired paddling
How to Steal $100 Million from the Perfect Smart Contract
50.【Application of dynamic two-dimensional array】
基于ModelArts的物体检测YOLOv3实践【玩转华为云】
【cartographer ros】十: 延时和误差分析
xss漏洞学习
Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (3) Background Functions
Qt supports HEIC/HEIF format images
What's up with VS "Cannot find or open PDB file"?How to solve
Google Earth Engine APP——15行代码搞定一个inspector高程监测APP