当前位置:网站首页>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日
边栏推荐
- MFC implementation road map navigation system
- STM32 Personal Notes - Watchdog
- 50.【Application of dynamic two-dimensional array】
- How programmers learn open source projects, this article tells you
- For small applications, which database is better to use?
- Mysql index related knowledge review one
- C#/VB.NET convert PPT or PPTX to image
- STM32 personal notes - program run and fly
- The use of scrapy crawler framework
- 将本地项目推送到远程仓库
猜你喜欢

VS“无法查找或打开PDB文件”是怎么回事?如何解决

自定义类型——枚举、联合

How to Steal $100 Million from the Perfect Smart Contract

PowerPC技术与市场杂谈

Qt supports HEIC/HEIF format images

Endorsed in 2022 years inventory | product base, science and technology, guangzhou automobile group striding forward
退役划水

WPF 截图控件之绘制箭头(五)「仿微信」

Visualization - Superset installation and deployment

图解MySQL内连接、外连接、左连接、右连接、全连接......太多了
随机推荐
rpm and yum
Introduction to STM32 development Introduce IIC bus, read and write AT24C02 (EEPROM) (using analog timing)
How programmers learn open source projects, this article tells you
基于ModelArts的物体检测YOLOv3实践【玩转华为云】
MacOS下postgresql(pgsql)数据库密码为什么不需要填写或可以乱填写
Mysql index related knowledge review one
2022年7月31日--使用C#迈出第一步--使用 C# 创建具有约定、空格和注释的易读代码
MTK6225-紧急电话
RK3399平台开发系列讲解(内核入门篇)1.52、printk函数分析 - 其函数调用时候会关闭中断
CTFshow,命令执行:web37
小程序毕设作品之微信美食菜谱小程序毕业设计成品(2)小程序功能
Yang Hui Triangle (C language implementation)
分类预测 | MATLAB实现1-DCNN一维卷积神经网络分类预测
Push the local project to the remote repository
WPF 截图控件之绘制箭头(五)「仿微信」
使用ESP32驱动QMA7981读取三轴加速度(带例程)
notes....
Mysql索引相关的知识复盘一
招聘随想2022
正则表达式