国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

ES6 Async/Await 完爆Promise的6個原因

shevy / 1232人閱讀

摘要:以往的異步方法無外乎回調(diào)函數(shù)和。當(dāng)然,對這個新特性也有一定的擔(dān)心,體現(xiàn)在他使得異步代碼變的不再明顯,我們好不容易已經(jīng)學(xué)會并習(xí)慣了使用回調(diào)函數(shù)或者來處理異步。

自從Node的7.6版本,已經(jīng)默認(rèn)支持async/await特性了。如果你還沒有使用過他,或者對他的用法不太了解,這篇文章會告訴你為什么這個特性“不容錯過”。本文輔以大量實例,相信你能很輕松的看懂,并了解Javascript處理異步的一大殺器。

文章靈感和內(nèi)容借鑒了6 Reasons Why JavaScript’s Async/Await Blows Promises Away (Tutorial),英文好的同學(xué)可以直接戳原版參考。

初識Async/await

對于還不了解Async/await特性的同學(xué),下面一段是一個“速成”培訓(xùn)。
Async/await 是Javascript編寫異步程序的新方法。以往的異步方法無外乎回調(diào)函數(shù)和Promise。但是Async/await建立于Promise之上。對于Javascript處理異步,是個老生常談卻歷久彌新的話題:

從最早的回調(diào)函數(shù),到 Promise 對象,再到 Generator 函數(shù),每次都有所改進,但又讓人覺得不徹底。它們都有額外的復(fù)雜性,都需要理解抽象的底層運行機制。
異步編程的最高境界,就是根本不用關(guān)心它是不是異步。

async 函數(shù)就是隧道盡頭的亮光,很多人認(rèn)為它是異步操作的終極解決方案。

Async/await語法

試想一下,我們有一個getJSON方法,該方法發(fā)送一個異步請求JSON數(shù)據(jù),并返回一個promise對象。這個promise對象的resolve方法傳遞異步獲得的JSON數(shù)據(jù)。具體例子的使用如下:

const makeRequest = () =>
    getJSON()
        .then(data => {
            console.log(data)
            return "done"
        })

makeRequest()

在使用async/await時,寫法如下:

const makeRequest = async () => {
    console.log(await getJSON())
    return "done"
}

makeRequest()

對比兩種寫法,針對第二種,我需要進一步說明:

1)第二種寫法(使用async/await),在主體函數(shù)之前使用了async關(guān)鍵字。在函數(shù)體內(nèi),使用了await關(guān)鍵字。當(dāng)然await關(guān)鍵字只能出現(xiàn)在用async聲明的函數(shù)體內(nèi)。該函數(shù)會隱式地返回一個Promise對象,函數(shù)體內(nèi)的return值,將會作為這個Promise對象resolve時的參數(shù)。
可以使用then方法添加回調(diào)函數(shù)。當(dāng)函數(shù)執(zhí)行的時候,一旦遇到await就會先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語句。

2)示例中,await getJSON() 說明console.log的調(diào)用,會等到getJSON()返回的promise對象resolve之后觸發(fā)。

我們在看一個例子加強一下理解,該例子取自阮一峰大神的《ECMAScript 6 入門》一書:

function timeout(ms) {
    return new Promise((resolve) => {
        setTimeout(resolve, ms);
    });
}

async function asyncPrint(value, ms) {
    await timeout(ms);
    console.log(value);
}

asyncPrint("hello world", 50);

上面代碼指定50毫秒以后,輸出hello world。

Async/await究竟好在哪里?

那么,同樣是處理異步操作,Async/await究竟好在哪里呢?
我們總結(jié)出以下6點。

簡約而干凈Concise and clean

我們看一下上面兩處代碼的代碼量,就可以直觀地看出使用Async/await對于代碼量的節(jié)省是很明顯的。對比Promise,我們不需要書寫.then,不需要新建一個匿名函數(shù)處理響應(yīng),也不需要再把數(shù)據(jù)賦值給一個我們其實并不需要的變量。同樣,我們避免了耦合的出現(xiàn)。這些看似很小的優(yōu)勢其實是很直觀的,在下面的代碼示例中,將會更加放大。

錯誤處理Error handling

Async/await使得處理同步+異步錯誤成為了現(xiàn)實。我們同樣使用try/catch結(jié)構(gòu),但是在promises的情況下,try/catch難以處理在JSON.parse過程中的問題,原因是這個錯誤發(fā)生在Promise內(nèi)部。想要處理這種情況下的錯誤,我們只能再嵌套一層try/catch,就像這樣:

const makeRequest = () => {
    try {
    getJSON()
        .then(result => {
            // this parse may fail
            const data = JSON.parse(result)
            console.log(data)
        })
        // uncomment this block to handle asynchronous errors
        // .catch((err) => {
        //   console.log(err)
        // })
        } 
    catch (err) {
        console.log(err)
    }
}

但是,如果用async/await處理,一切變得簡單,解析中的錯誤也能輕而易舉的解決:

 const makeRequest = async () => {
      try {
          // this parse may fail
          const data = JSON.parse(await getJSON())
          console.log(data)
      } 
      catch (err) {
          console.log(err)
      }
   }
條件判別Conditionals

想象一下這樣的業(yè)務(wù)需求:我們需要先拉取數(shù)據(jù),然后根據(jù)得到的數(shù)據(jù)判斷是否輸出此數(shù)據(jù),或者根據(jù)數(shù)據(jù)內(nèi)容拉取更多的信息。如下:

const makeRequest = () => {
    return getJSON()
        .then(data => {
            if (data.needsAnotherRequest) {
                return makeAnotherRequest(data)
                        .then(moreData => {
                            console.log(moreData)
                            return moreData
                        })
            } 
            else {
                console.log(data)
                return data
            }
        })
}

這樣的代碼會讓我們看的頭疼。這這么多層(6層)嵌套過程中,非常容易“丟失自我”。
使用async/await,我們就可以輕而易舉的寫出可讀性更高的代碼:

const makeRequest = async () => {
    const data = await getJSON()
    if (data.needsAnotherRequest) {
        const moreData = await makeAnotherRequest(data);
        console.log(moreData)
        return moreData
    } 
    else {
        console.log(data)
        return data    
    }
}
中間值Intermediate values

一個經(jīng)常出現(xiàn)的場景是,我們先調(diào)起promise1,然后根據(jù)返回值,調(diào)用promise2,之后再根據(jù)這兩個Promises得值,調(diào)取promise3。使用Promise,我們不難實現(xiàn):

const makeRequest = () => {
    return promise1()
        .then(value1 => {
            // do something
            return promise2(value1)
                .then(value2 => {
                    // do something          
                    return promise3(value1, value2)
                })
        })
}

如果你難以忍受這樣的代碼,我們可以優(yōu)化我們的Promise,方案是使用Promise.all來避免很深的嵌套。
就像這樣:

const makeRequest = () => {
    return promise1()
        .then(value1 => {
            // do something
            return Promise.all([value1, promise2(value1)])
        })
        .then(([value1, value2]) => {
            // do something          
            return promise3(value1, value2)
        })
}

Promise.all這個方法犧牲了語義性,但是得到了更好的可讀性。
但是其實,把value1 & value2一起放到一個數(shù)組中,是很“蛋疼”的,某種意義上也是多余的。

同樣的場景,使用async/await會非常簡單:

const makeRequest = async () => {
    const value1 = await promise1()
    const value2 = await promise2(value1)
    return promise3(value1, value2)
}
錯誤堆棧信息Error stacks

想象一下我們鏈?zhǔn)秸{(diào)用了很多promises,一級接一級。緊接著,這條promises鏈中某處出錯,如下:

const makeRequest = () => {
    return callAPromise()
        .then(() => callAPromise())
        .then(() => callAPromise())
        .then(() => callAPromise())
        .then(() => callAPromise())
        .then(() => {
            throw new Error("oops");
        })
}

makeRequest()
    .catch(err => {
        console.log(err);
        // output
        // Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
    })

此鏈條的錯誤堆棧信息并沒用線索指示錯誤到底出現(xiàn)在哪里。更糟糕的事,他還會誤導(dǎo)開發(fā)者:錯誤信息中唯一出現(xiàn)的函數(shù)名稱其實根本就是無辜的。
我們再看一下async/await的展現(xiàn):

const makeRequest = async () => {
    await callAPromise()
    await callAPromise()
    await callAPromise()
    await callAPromise()
    await callAPromise()
    throw new Error("oops");
}

makeRequest()
    .catch(err => {
        console.log(err);
        // output
        // Error: oops at makeRequest (index.js:7:9)
    })

也許這樣的對比,對于在本地開發(fā)階段區(qū)別不是很大。但是想象一下在服務(wù)器端,線上代碼的錯誤日志情況下,將會變得非常有意義。你一定會覺得上面這樣的錯誤信息,比“錯誤出自一個then的then的then。。。”有用的多。

調(diào)試Debugging

最后一點,但是也是很重要的一點,使用async/await來debug會變得非常簡單。
在一個返回表達式的箭頭函數(shù)中,我們不能設(shè)置斷點,這就會造成下面的局面:

const makeRequest = () => {
    return callAPromise()
        .then(()=>callAPromise())
        .then(()=>callAPromise())
        .then(()=>callAPromise())
        .then(()=>callAPromise())
}

我們無法在每一行設(shè)置斷點。但是使用async/await時:

const makeRequest = async () => {
    await callAPromise()
    await callAPromise()
    await callAPromise()
    await callAPromise()
}
總結(jié)

Async/await是近些年來JavaScript最具革命性的新特性之一。他讓讀者意識到使用Promise存在的一些問題,并提供了自身來代替Promise的方案。
當(dāng)然,對這個新特性也有一定的擔(dān)心,體現(xiàn)在:
他使得異步代碼變的不再明顯,我們好不容易已經(jīng)學(xué)會并習(xí)慣了使用回調(diào)函數(shù)或者.then來處理異步。新的特性當(dāng)然需要時間成本去學(xué)習(xí)和體會;
退回來說,熟悉C#語言的程序員一定會懂得這些學(xué)習(xí)成本是完全值得的。

Happy Coding!

PS: 作者Github倉庫,歡迎通過代碼各種形式交流。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/82492.html

相關(guān)文章

  • ES6 Async/Await 完爆Promise6原因

    摘要:以往的異步方法無外乎回調(diào)函數(shù)和。當(dāng)然,對這個新特性也有一定的擔(dān)心,體現(xiàn)在他使得異步代碼變的不再明顯,我們好不容易已經(jīng)學(xué)會并習(xí)慣了使用回調(diào)函數(shù)或者來處理異步。 自從Node的7.6版本,已經(jīng)默認(rèn)支持async/await特性了。如果你還沒有使用過他,或者對他的用法不太了解,這篇文章會告訴你為什么這個特性不容錯過。本文輔以大量實例,相信你能很輕松的看懂,并了解Javascript處理異步的...

    W4n9Hu1 評論0 收藏0
  • ES6-7

    摘要:的翻譯文檔由的維護很多人說,阮老師已經(jīng)有一本關(guān)于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發(fā)過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復(fù)雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...

    mudiyouyou 評論0 收藏0
  • 為微信小程序開發(fā)網(wǎng)易云音樂api庫

    摘要:之前我們已經(jīng)開發(fā)過一款小程序適用的音樂庫,這次開發(fā)網(wǎng)易云音樂庫的原因是音樂庫在小程序中環(huán)境下無法使用小程序提供的背景音頻播放器播放的問題網(wǎng)易云的加密算法真的比其他幾家復(fù)雜太多了。。。 之前我們已經(jīng)開發(fā)過一款小程序適用的qq音樂api庫https://github.com/FisherWY/Q...,這次開發(fā)網(wǎng)易云音樂api庫的原因是qq音樂api庫在小程序中iOS環(huán)境下無法使用小程序提...

    Codeing_ls 評論0 收藏0
  • 【W(wǎng)eb全棧課程三】ES6特性介紹(下)

    摘要:示例運行函數(shù)彈出彈出函數(shù)接收參數(shù),返回值。其中,返回一個對象,是的返回值,代表函數(shù)是否執(zhí)行完成。 ES6特性介紹(下) ES6新的標(biāo)準(zhǔn),新的語法特征:1、變量/賦值2、函數(shù)3、數(shù)組/json4、字符串5、面向?qū)ο?、Promise7、generator8、ES7:async/await 《【W(wǎng)eb全棧課程二】ES6特性介紹(上)》見:https://segmentfault.com/a...

    wangshijun 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<