首页IT科技js async defer(ES6+–》熟知JS中的async函数)

js async defer(ES6+–》熟知JS中的async函数)

时间2025-06-21 01:28:32分类IT科技浏览4051
导读:目录...

目录

async函数

await 表达式

async使用形式

async读取文件

async发送AJAX请求

与生成器(Generator)相比

async函数

async函数的返回值为 promise 对象            ,promise对象的结果由async函数执行的返回值决定            。async函数能使得异步操作变得更加方便                  ,简而言之就是 Generator 的语法糖                 。

定义async函数     ,特点是即便函数内部返回结果不是promise对象      ,调用函数其最后的返回结果依然是promise对象                  ,代码如下:

如果返回的结果不是 Promise 对象的情况下:

<script> async function fn(){ // 返回的结果是字符串 // return 123 // // 返回的结果是undefined // return; // 返回的结果是抛出一个异常 throw new error } const result = fn() console.log(result); </script>

如果返回的结果是 Promise 对象时           ,我们正常使用 then 方法即可      ,如下:

<script> async function fn(){ return new Promise((resolve,reject)=>{ // resolve(成功的数据) reject(失败的数据) }) } const result = fn() // 调用 then 方法 result.then((value)=>{ console.log(value); },(reason)=>{ console.log(reason); // 打印失败的数据 }) </script>

await 表达式

通过上文的对 async 介绍                  ,感觉其功能有点鸡肋           ,其实恰恰不是,而是 async 需要搭配 await 一起使用才能达到语法糖的效果      。

await的特点

await必须写在 async 函数中

await右侧的表达式一般为 promise 对象

await返回的是 promise 成功的值

await的 promise 失败了                  ,就会抛出异常                 ,需要通过 try...catch捕获处理

说白了:await就相当于 then 方法的第一个回调函数,只返回成功的值            ,失败的值需要 try...catch来捕获            。

async函数内部抛出错误                 ,会导致返回的 Promise 对象变为reject状态                 。抛出的错误对象会被catch方法回调函数接收到      。

<script> const p = new Promise((resolve,reject)=>{ // resolve(用户数据) reject(用户加载数据失败了) }) async function fn(){ // 为防止promise是失败的状态     ,加上try...catch进行异常捕获 try { // await 返回的结果就是 promise 返回成功的值 let result = await p console.log(result); } catch (error) { console.log(error);//因为是失败的状态            ,所以打印:用户加载数据失败了 } } fn() </script>

总结

(1)await命令后面的Promise对象                  ,运行结果可能是rejected     ,所以最好把await命令放在try...catch代码块中      。

(2)如果有多个await命令后面的异步操作      ,如果不存在继发关系                  ,最好让它们同时触发                 。

比如:await Promise.all([a(), b()])           ,这里简单提一下

(3)await命令只能用在async函数之中      ,如果用在普通函数                  ,就会报错            。

(4)(理解一下async的运行原理) async 函数可以保留运行堆栈           ,普通函数内部运行一个异步任务时,如果异步任务运行结束普通函数可能早就运行完了                  ,异步任务的上下文环境已经消失了                 ,如果异步任务报错,错误堆栈将不包括普通函数;而async函数内部的异步任务运行时            ,async函数是暂停执行的                 ,所以一旦async函数内部的异步任务运行报错     ,错误堆栈将包括async函数      。

async使用形式

// 函数声明 async function foo() {} // 函数表达式 const foo = async function () {}; // 对象的方法 let obj = { async foo() {} }; obj.foo().then(...) // Class 的方法 class Storage { constructor() { this.cachePromise = caches.open(avatars); } async getAvatar(name) { const cache = await this.cachePromise; return cache.match(`/avatars/${name}.jpg`); } } const storage = new Storage(); storage.getAvatar(jake).then(…); // 箭头函数 const foo = async () => {};

async读取文件

和之前讲解的 promise 读取文件内容 一样            ,我们也可以使用async进行文件的读取                  ,代码如下:

// 1.引入 fs 模块 const fs = require(fs) // 2.读取文件 function index(){ return new Promise((resolve,reject)=>{ fs.readFile(./index.md,(err,data)=>{ // 如果失败 if(err) reject(err) // 如果成功 resolve(data) }) }) } function index1(){ return new Promise((resolve,reject)=>{ fs.readFile(./index1.md,(err,data)=>{ // 如果失败 if(err) reject(err) // 如果成功 resolve(data) }) }) } function index2(){ return new Promise((resolve,reject)=>{ fs.readFile(./index2.md,(err,data)=>{ // 如果失败 if(err) reject(err) // 如果成功 resolve(data) }) }) } // 3.声明一个 async 函数 async function fn(){ let i = await index() let i1 = await index1() let i2 = await index2() console.log(i.toString()); console.log(i1.toString()); console.log(i2.toString()); } fn()

async发送AJAX请求

和之前讲解 promise发送ajax请求 一样     ,我们也可以使用async进行发送ajax请求      ,代码如下:

<script> // 发送 AJAX请求                  ,返回的结果是 Promise 对象 function sendAjax(url){ return new Promise((resolve,reject)=>{ // 创建对象 const x = new XMLHttpRequest() // 初始化 x.open(GET,url) // 发送 x.send() // 事件绑定 x.onreadystatechange = function(){ if(x.readyState === 4){ if(x.status >= 200 && x.status < 300){ // 如果响应成功 resolve(x.response) // 如果响应失败 reject(x.status) } } } }) } // promise then 方法测试 // const result = sendAjax("https://ai.baidu.com/").then(value=>{ // console.log(value); // },reason=>{}) // async 与 await 测试 async function fn(){ // 发送 AJAX 请求 let result = await sendAjax("https://ai.baidu.com/") console.log(result); } fn() </script>

与生成器(Generator)相比

我们发现 async与await之间的关系 和 Generator与yield之间的关系十分类似           ,不熟悉Generator的朋友可以看一下我之前的文章:生成器讲解 ;一比较就发现: async函数就是将 Generator 函数的星号(*)替换成async      ,将yield替换成await                 。代码比较如下:

<script> // Generator 函数 function * person() { console.log(hello world); yield 第一分隔线 console.log(hello world 1); yield 第二分隔线 console.log(hello world 2); yield 第三分隔线 } let iterator = person() // console.log(iterator); 打印的就是一个迭代器对象                  ,里面有一个 next() 方法           ,我们借助next方法让它运行 iterator.next() iterator.next() iterator.next() // async函数 const person1 = async function (){ console.log(hello world); await 第一分隔线 console.log(hello world 1); await 第二分隔线 console.log(hello world 2); await 第三分隔线 } person1() </script>

async函数的实现原理就是将 Generator 函数和自动执行器包装在一个函数里            。

<script> async function fn(args) {} // 等同于 function fn(args) { // spawn函数就是自动执行器 return spawn(function* () {}); } </script>

我们可以分析一下 Generator 和 async 代码的书写特点和风格:

<script> // Generator 函数 function Generator(a, b) { return spawn(function*() { let r = null; try { for(let k of b) { r = yield k(a); } } catch(e) { /* 忽略错误,继续执行 */ } return r; }); } // async 函数 async function async(a, b) { let r = null; try { for(let k of b) { r = await k(a); } } catch(e) { /* 忽略错误                  ,继续执行 */ } return r; } </script>

所以 async 函数的实现符合语义也很简洁                 ,不用写Generator的自动执行器,改在语言底层提供            ,因此代码量少。 

从上文代码我们可以总结以下几点

(1)Generator函数执行需要借助执行器                 ,而async函数自带执行器     ,即async不需要像生成器一样需要借助 next 方法才能执行            ,而是会自动执行                 。

(2)相比于生成器函数                  ,我们可以看到 async 函数的语义更加清晰

(3)上面就说了     ,async函数可以接受Promise或者其他原始类型      ,而生成器函数yield命令后面只能是Promise对象或者Thunk函数                 。

(4)async函数返回值只能是Promise对象                  ,而生成器函数返回值是 Iterator 对象

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
function 箭头函数 this(JavaScript箭头函数与普通函数的区别示例详解)