最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript異步編程中async函數(shù)詳解

 更新時間:2022年11月08日 11:56:27   作者:亦世凡華、  
async函數(shù)是使用async關(guān)鍵字聲明的函數(shù)。 async函數(shù)是AsyncFunction構(gòu)造函數(shù)的實例, 并且其中允許使用await關(guān)鍵字。async和await關(guān)鍵字讓我們可以用一種更簡潔的方式寫出基于Promise的異步行為,而無需刻意地鏈式調(diào)用promise

async函數(shù)

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

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

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

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

如果返回的結(jié)果是 Promise 對象時,我們正常使用 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>

await 表達式

通過上文的對 async 介紹,感覺其功能有點雞肋,其實恰恰不是,而是 async 需要搭配 await 一起使用才能達到語法糖的效果。

await的特點:

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

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

await返回的是 promise 成功的值

await的 promise 失敗了,就會拋出異常,需要通過 try...catch捕獲處理

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

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

<script>
    const p = new Promise((resolve,reject)=>{
        // resolve('用戶數(shù)據(jù)')
        reject('用戶加載數(shù)據(jù)失敗了')
    })
    async function fn(){
        // 為防止promise是失敗的狀態(tài),加上try...catch進行異常捕獲
        try {
            // await 返回的結(jié)果就是 promise 返回成功的值
            let result = await p
            console.log(result);
        } catch (error) {
            console.log(error);//因為是失敗的狀態(tài),所以打?。河脩艏虞d數(shù)據(jù)失敗了
        }
    }
    fn()
</script>

總結(jié):

(1)await命令后面的Promise對象,運行結(jié)果可能是rejected,所以最好把await命令放在try...catch代碼塊中。

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

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

(3)await命令只能用在async函數(shù)之中,如果用在普通函數(shù),就會報錯。

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

async使用形式

// 函數(shù)聲明
async function foo() {}
// 函數(shù)表達式
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(…);
// 箭頭函數(shù)
const foo = async () => {};

async讀取文件

和之前講解的 promise 讀取文件內(nèi)容 一樣,我們也可以使用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 函數(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()

async發(fā)送AJAX請求

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

<script>
    // 發(fā)送 AJAX請求,返回的結(jié)果是 Promise 對象
    function sendAjax(url){
        return new Promise((resolve,reject)=>{
            // 創(chuàng)建對象
            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 方法測試
    // const result = sendAjax("https://ai.baidu.com/").then(value=>{
    //     console.log(value);
    // },reason=>{})
    // async 與 await 測試
    async function fn(){
        // 發(fā)送 AJAX 請求
        let result = await sendAjax("https://ai.baidu.com/")
        console.log(result);
    }
    fn()
</script>

與生成器(Generator)相比

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

<script>
    // Generator 函數(shù)
    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函數(shù)
    const person1 = async function (){
        console.log('hello world');
        await '第一分隔線' 
        console.log('hello world 1');
        await '第二分隔線'
        console.log('hello world 2');
        await '第三分隔線'
    }
    person1()
</script>

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

<script>
    async function fn(args) {}
    // 等同于
    function fn(args) {
        // spawn函數(shù)就是自動執(zhí)行器
        return spawn(function* () {});
    }
</script>

我們可以分析一下 Generator 和 async 代碼的書寫特點和風(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) {
                /* 忽略錯誤,繼續(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) {
         /* 忽略錯誤,繼續(xù)執(zhí)行 */
        }
        return r;
    }
</script>

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

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

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

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

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

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

到此這篇關(guān)于JavaScript異步編程中async函數(shù)詳解的文章就介紹到這了,更多相關(guān)JS async內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解js數(shù)組的完全隨機排列算法

    詳解js數(shù)組的完全隨機排列算法

    本文主要對常見的完全錯誤的隨機排列算法進行介紹分析,并介紹了經(jīng)典的隨機排列算法,具有很好的參考價值,需要的朋友一起來看下吧
    2016-12-12
  • 釘釘小程序web-view內(nèi)嵌H5頁面并實現(xiàn)通信

    釘釘小程序web-view內(nèi)嵌H5頁面并實現(xiàn)通信

    本文主要介紹了釘釘小程序web-view內(nèi)嵌H5頁面并實現(xiàn)通信,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • javascript創(chuàng)建cookie、讀取cookie

    javascript創(chuàng)建cookie、讀取cookie

    這篇文章主要介紹了javascript創(chuàng)建cookie、讀取cookie的操作方法,內(nèi)容簡單易學(xué),感興趣的小伙伴們可以參考一下
    2016-03-03
  • js獲取對象的屬性值兩種方式

    js獲取對象的屬性值兩種方式

    這篇文章主要介紹了js獲取對象的屬性值兩種方式,在JavaScript中訪問對象的屬性值可以通過點運算符(.)或括號運算符([])兩種方式,文中將兩種方式的代碼介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • 原生js實現(xiàn)淘寶放大鏡效果

    原生js實現(xiàn)淘寶放大鏡效果

    這篇文章主要為大家詳細介紹了原生js實現(xiàn)放大鏡效果,制作一個類似于淘寶的放大鏡效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • CSS常用網(wǎng)站布局實例

    CSS常用網(wǎng)站布局實例

    PS:這里列出的是常用的例子,而非研究之用,對一每個盒子,都沒有設(shè)置margin,padding,boeder等屬性!
    2008-04-04
  • JavaScript  event對象整理及詳細介紹

    JavaScript event對象整理及詳細介紹

    這篇文章主要介紹了JavaScript event對象整理及詳細介紹的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 使用有限狀態(tài)機實現(xiàn)簡版的html解析器

    使用有限狀態(tài)機實現(xiàn)簡版的html解析器

    FSM(Finite State Machines) 有限狀態(tài)機,也叫有限狀態(tài)自動機,是為研究有限內(nèi)存的計算過程和某些語言類而抽象出的一種計算模型,本文將使用有限狀態(tài)機實現(xiàn)一個簡版的html解析器,有需要的小伙伴可以參考下
    2023-11-11
  • javascript 中模板方法單例的實現(xiàn)方法

    javascript 中模板方法單例的實現(xiàn)方法

    這篇文章主要介紹了javascript 中模板方法單例的實現(xiàn)方法的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-10-10
  • 僅一個form表單 js實現(xiàn)注冊信息依次填寫提交功能

    僅一個form表單 js實現(xiàn)注冊信息依次填寫提交功能

    這篇文章主要為大家詳細介紹了僅一個form表單,JavaScript可實現(xiàn)注冊信息依次填寫提交功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-06-06

最新評論

香格里拉县| 濮阳市| 德清县| 正宁县| 抚顺市| 石门县| 宁河县| 周宁县| 格尔木市| 永胜县| 济阳县| 荔波县| 博客| 牙克石市| 鱼台县| 郯城县| 同心县| 马公市| 皮山县| 宁都县| 平度市| 林甸县| 玉溪市| 潞西市| 巫溪县| 蒲江县| 邵阳县| 项城市| 红原县| 吉木乃县| 杭锦旗| 大名县| 平凉市| 隆化县| 阿勒泰市| 调兵山市| 青冈县| 汉阴县| 平昌县| 获嘉县| 咸丰县|