亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長(zhǎng)資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    深入探討JavaScript中的async函數(shù)

    深入探討JavaScript中的async函數(shù)

    前端(vue)入門(mén)到精通課程:進(jìn)入學(xué)習(xí)
    Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調(diào)試工具:點(diǎn)擊使用

    async函數(shù)

    async函數(shù)的返回值為 promise 對(duì)象,promise對(duì)象的結(jié)果由async函數(shù)執(zhí)行的返回值決定。async函數(shù)能使得異步操作變得更加方便,簡(jiǎn)而言之就是 Generator 的語(yǔ)法糖。

    定義async函數(shù),特點(diǎn)是即便函數(shù)內(nèi)部返回結(jié)果不是promise對(duì)象,調(diào)用函數(shù)其最后的返回結(jié)果依然是promise對(duì)象,代碼如下:

    如果返回的結(jié)果不是 Promise 對(duì)象的情況下:

    <script>     async function fn(){         // 返回的結(jié)果是字符串         // return '123'         // // 返回的結(jié)果是undefined         // return;         // 返回的結(jié)果是拋出一個(gè)異常         throw new 'error'     }     const result = fn()     console.log(result); </script>
    登錄后復(fù)制

    深入探討JavaScript中的async函數(shù)

    如果返回的結(jié)果是 Promise 對(duì)象時(shí),我們正常使用 then 方法即可,如下:

    <script>     async function fn(){         return new Promise((resolve,reject)=>{             // resolve('成功的數(shù)據(jù)')             reject('失敗的數(shù)據(jù)')         })     }     const result = fn()     // 調(diào)用 then 方法     result.then((value)=>{         console.log(value);     },(reason)=>{         console.log(reason); // 打印失敗的數(shù)據(jù)     }) </script>
    登錄后復(fù)制

    await 表達(dá)式

    通過(guò)上文的對(duì) async 介紹,感覺(jué)其功能有點(diǎn)雞肋,其實(shí)恰恰不是,而是 async 需要搭配 await 一起使用才能達(dá)到語(yǔ)法糖的效果。

    await的特點(diǎn)

    await必須寫(xiě)在 async 函數(shù)中

    await右側(cè)的表達(dá)式一般為 promise 對(duì)象

    await返回的是 promise 成功的值

    await的 promise 失敗了,就會(huì)拋出異常,需要通過(guò) try…catch捕獲處理

    說(shuō)白了:await就相當(dāng)于 then 方法的第一個(gè)回調(diào)函數(shù),只返回成功的值,失敗的值需要 try…catch來(lái)捕獲。

    async函數(shù)內(nèi)部拋出錯(cuò)誤,會(huì)導(dǎo)致返回的 Promise 對(duì)象變?yōu)閞eject狀態(tài)。拋出的錯(cuò)誤對(duì)象會(huì)被catch方法回調(diào)函數(shù)接收到。

    <script>     const p = new Promise((resolve,reject)=>{         // resolve('用戶(hù)數(shù)據(jù)')         reject('用戶(hù)加載數(shù)據(jù)失敗了')     })     async function fn(){         // 為防止promise是失敗的狀態(tài),加上try...catch進(jìn)行異常捕獲         try {             // await 返回的結(jié)果就是 promise 返回成功的值             let result = await p             console.log(result);         } catch (error) {             console.log(error);//因?yàn)槭鞘〉臓顟B(tài),所以打?。河脩?hù)加載數(shù)據(jù)失敗了         }     }     fn() </script>
    登錄后復(fù)制

    總結(jié)

    (1)await命令后面的Promise對(duì)象,運(yùn)行結(jié)果可能是rejected,所以最好把a(bǔ)wait命令放在try…catch代碼塊中。

    (2)如果有多個(gè)await命令后面的異步操作,如果不存在繼發(fā)關(guān)系,最好讓它們同時(shí)觸發(fā)。

    比如:await Promise.all([a(), b()]),這里簡(jiǎn)單提一下

    (3)await命令只能用在async函數(shù)之中,如果用在普通函數(shù),就會(huì)報(bào)錯(cuò)。

    (4)(理解一下async的運(yùn)行原理) async 函數(shù)可以保留運(yùn)行堆棧,普通函數(shù)內(nèi)部運(yùn)行一個(gè)異步任務(wù)時(shí),如果異步任務(wù)運(yùn)行結(jié)束普通函數(shù)可能早就運(yùn)行完了,異步任務(wù)的上下文環(huán)境已經(jīng)消失了,如果異步任務(wù)報(bào)錯(cuò),錯(cuò)誤堆棧將不包括普通函數(shù);而async函數(shù)內(nèi)部的異步任務(wù)運(yùn)行時(shí),async函數(shù)是暫停執(zhí)行的,所以一旦async函數(shù)內(nèi)部的異步任務(wù)運(yùn)行報(bào)錯(cuò),錯(cuò)誤堆棧將包括async函數(shù)。

    async使用形式

    // 函數(shù)聲明 async function foo() {}   // 函數(shù)表達(dá)式 const foo = async function () {};   // 對(duì)象的方法 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(…);   // 箭頭函數(shù) const foo = async () => {};
    登錄后復(fù)制

    async讀取文件

    和之前講解的 promise 讀取文件內(nèi)容 一樣,我們也可以使用async進(jìn)行文件的讀取,代碼如下:

    // 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.聲明一個(gè) async 函數(shù) 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()
    登錄后復(fù)制

    深入探討JavaScript中的async函數(shù)

    async發(fā)送AJAX請(qǐng)求

    和之前講解 promise發(fā)送ajax請(qǐng)求 一樣,我們也可以使用async進(jìn)行發(fā)送ajax請(qǐng)求,代碼如下:

    <script>     // 發(fā)送 AJAX請(qǐng)求,返回的結(jié)果是 Promise 對(duì)象     function sendAjax(url){         return new Promise((resolve,reject)=>{             // 創(chuàng)建對(duì)象             const x = new XMLHttpRequest()               // 初始化             x.open('GET',url)               // 發(fā)送             x.send()               // 事件綁定             x.onreadystatechange = function(){                 if(x.readyState === 4){                     if(x.status >= 200 && x.status < 300){                         // 如果響應(yīng)成功                         resolve(x.response)                         // 如果響應(yīng)失敗                         reject(x.status)                     }                 }             }         })     }              // promise then 方法測(cè)試     // const result = sendAjax("https://ai.baidu.com/").then(value=>{     //     console.log(value);     // },reason=>{})     // async 與 await 測(cè)試     async function fn(){         // 發(fā)送 AJAX 請(qǐng)求         let result = await sendAjax("https://ai.baidu.com/")         console.log(result);     }     fn() </script>
    登錄后復(fù)制

    深入探討JavaScript中的async函數(shù)

    與生成器(Generator)相比

    我們發(fā)現(xiàn) async與await之間的關(guān)系 和 Generator與yield之間的關(guān)系十分類(lèi)似,不熟悉Generator的朋友可以看一下我之前的文章:生成器講解 ;一比較就發(fā)現(xiàn): async函數(shù)就是將 Generator 函數(shù)的星號(hào)(*)替換成async,將yield替換成await。代碼比較如下:

    <script>     // Generator 函數(shù)     function * person() {         console.log('hello world');         yield '第一分隔線(xiàn)'               console.log('hello world 1');         yield '第二分隔線(xiàn)'              console.log('hello world 2');         yield '第三分隔線(xiàn)'     }     let iterator = person()     // console.log(iterator); 打印的就是一個(gè)迭代器對(duì)象,里面有一個(gè) next() 方法,我們借助next方法讓它運(yùn)行     iterator.next()     iterator.next()     iterator.next()       // async函數(shù)     const person1 = async function (){         console.log('hello world');         await '第一分隔線(xiàn)'               console.log('hello world 1');         await '第二分隔線(xiàn)'              console.log('hello world 2');         await '第三分隔線(xiàn)'     }     person1() </script>
    登錄后復(fù)制

    深入探討JavaScript中的async函數(shù)

    async函數(shù)的實(shí)現(xiàn)原理就是將 Generator 函數(shù)和自動(dòng)執(zhí)行器包裝在一個(gè)函數(shù)里。

    <script>     async function fn(args) {}     // 等同于     function fn(args) {         // spawn函數(shù)就是自動(dòng)執(zhí)行器         return spawn(function* () {});     } </script>
    登錄后復(fù)制

    我們可以分析一下 Generator 和 async 代碼的書(shū)寫(xiě)特點(diǎn)和風(fēng)格:

    <script>     // Generator 函數(shù)     function Generator(a, b) {         return spawn(function*() {             let r = null;             try {                 for(let k of b) {                 r = yield k(a);                 }             } catch(e) {                 /* 忽略錯(cuò)誤,繼續(xù)執(zhí)行 */             }             return r;         });     }       // async 函數(shù)     async function async(a, b) {         let r = null;         try {             for(let k of b) {             r = await k(a);             }         } catch(e) {          /* 忽略錯(cuò)誤,繼續(xù)執(zhí)行 */         }         return r;     } </script>
    登錄后復(fù)制

    所以 async 函數(shù)的實(shí)現(xiàn)符合語(yǔ)義也很簡(jiǎn)潔,不用寫(xiě)Generator的自動(dòng)執(zhí)行器,改在語(yǔ)言底層提供,因此代碼量少。

    從上文代碼我們可以總結(jié)以下幾點(diǎn)

    (1)Generator函數(shù)執(zhí)行需要借助執(zhí)行器,而async函數(shù)自帶執(zhí)行器,即async不需要像生成器一樣需要借助 next 方法才能執(zhí)行,而是會(huì)自動(dòng)執(zhí)行。

    (2)相比于生成器函數(shù),我們可以看到 async 函數(shù)的語(yǔ)義更加清晰

    (3)上面就說(shuō)了,async函數(shù)可以接受Promise或者其他原始類(lèi)型,而生成器函數(shù)yield命令后面只能是Promise對(duì)象或者Thunk函數(shù)。

    (4)async函數(shù)返回值只能是Promise對(duì)象,而生成器函數(shù)返回值是 Iterator 對(duì)象

    【推薦學(xué)習(xí):javascript高級(jí)教程】

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)