亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專(zhuān)欄INFORMATION COLUMN

【譯】async/await 應(yīng)知應(yīng)會(huì)

Ku_Andrew / 2011人閱讀

摘要:原文地址原文作者翻譯作者是在版本中引入的,它對(duì)于中的異步編程而言是一個(gè)巨大的提升??赡軙?huì)產(chǎn)生誤導(dǎo)一些文章把和進(jìn)行了比較,同時(shí)說(shuō)它是異步編程演變過(guò)程中的下一代解決方案,對(duì)此我不敢茍同。結(jié)論在中引入的關(guān)鍵字無(wú)疑是對(duì)異步編程的一大加強(qiáng)。

原文地址: https://hackernoon.com/javasc...

原文作者: Charlee Li

翻譯作者: Xixi20160512

async/await 是在 ES7 版本中引入的,它對(duì)于 JavaScript 中的異步編程而言是一個(gè)巨大的提升。它可以讓我們以同步的方式處理異步的流程,同時(shí)不會(huì)阻塞主線(xiàn)程。但是,想要用好這一特性,可能需要?jiǎng)狱c(diǎn)腦筋。本文中,我們將從不同的角度探討 async/await,同時(shí)會(huì)展示如何正確和高效的使用它們。

async/await 的優(yōu)點(diǎn)

async/await帶給我們最大的一個(gè)好處就是同步的編程風(fēng)格。讓我們看一個(gè)例子:

// async/await
async getBooksByAuthorWithAwait(authorId) {
    const books = await bookModel.fetchAll();  
    return books.filter(b => b.authorId === authorId);
}
// promise
getBooksByAuthorWithPromise(authorId) { 
    return bookModel.fetchAll()
        .then(books => books.filter(b => b.authorId === authorId));
}

很明顯,async/await 的版本比 promise 的版本更加的易于理解。如果你忽略 await 關(guān)鍵字,這段代碼看起來(lái)就像任何其他的同步式語(yǔ)言(比如說(shuō) Python)。

不僅僅是可讀性,async/await 有瀏覽器的原生支持。到今天為止,所有主流瀏覽器都支持 async 函數(shù)。

所有主流瀏覽器都支持 async 函數(shù)。(圖片來(lái)源:https://caniuse.com/)

原生支持意味著你不需要編譯代碼。更重要的是,這個(gè)將有助于調(diào)試。當(dāng)你在 async 方法的入口打一個(gè)斷點(diǎn)并且步進(jìn)到 await 這一行的時(shí)候,你將會(huì)看到調(diào)試器在 bookModel.fetchAll() 這個(gè)函數(shù)執(zhí)行的時(shí)候等待了一會(huì)兒,然后才會(huì)走到接下來(lái)的 .filter 這一行!和 promise 的示例比較起來(lái),這個(gè)容易多了,因?yàn)槟惚仨氃?.filter 這一行再打一個(gè)斷點(diǎn)。

調(diào)試 async 函數(shù)。調(diào)試器會(huì)在 await 這一行等待執(zhí)行完成然后才會(huì)移動(dòng)到下一行。

另一個(gè)不那么明顯的好處就是 async 關(guān)鍵字。它聲明了 getBooksByAuthorWithAwait() 方法返回的是一個(gè) promise,因此調(diào)用者可以像 getBooksByAuthorWithAwait().then(...) 或者 await getBooksByAuthorWithAwait() 這樣安全的調(diào)用??匆幌逻@個(gè)例子(不好的實(shí)踐):

getBooksByAuthorWithPromise(authorId) {  
    if (!authorId) {    return null;  }  
    return bookModel.fetchAll()    
        .then(books => books.filter(b => b.authorId === authorId));
}

在上面的代碼中,getBooksByAuthorWithPromise 可能返回一個(gè) promise (正常情況下)或者 null (特殊情況下),返回 null 的時(shí)候調(diào)用者不能安全的調(diào)用 .then() 。使用 async 進(jìn)行聲明的時(shí)候,這個(gè)問(wèn)題就不會(huì)存在了。

Async/await 可能會(huì)產(chǎn)生誤導(dǎo)

一些文章把 async/await 和 Promise 進(jìn)行了比較,同時(shí)說(shuō)它是 JavaScript 異步編程演變過(guò)程中的下一代解決方案,對(duì)此我不敢茍同。Async/await 是一個(gè)提升,但它僅僅是一個(gè)語(yǔ)法糖,它將不會(huì)完全的改變我們的編程風(fēng)格。

實(shí)質(zhì)上,async 函數(shù)仍然是 promise。你必須理解 promises 之后才能正確的使用 async 函數(shù),更糟糕的是,大多數(shù)情況下你必須同時(shí)使用 promises 和 async 函數(shù)。

思考一下上面例子中使用到 的 getBooksByAuthorWithAwait()getBooksByAuthorWithPromises() 。請(qǐng)注意,它們不僅是有相同的功能,同時(shí)也有相同的接口。

這意味著如果你直接 getBooksByAuthorWithAwait() 的話(huà),將會(huì)返回一個(gè) promise。

當(dāng)然,這并不是一件不好的事情。只有 await 給人們的一種感覺(jué),“很棒,這個(gè)可以將異步的函數(shù)轉(zhuǎn)換成同步的函數(shù)”,這個(gè)才是錯(cuò)誤的。

Async/await 的陷阱

那么在使用 async/await 的過(guò)程中會(huì)犯哪些錯(cuò)誤呢?這里有一些比較常見(jiàn)的例子。

過(guò)于線(xiàn)性化

雖然 await 能夠使你的代碼看起來(lái)像同步代碼一樣,但是一定要記住這些代碼仍然是以異步的方式執(zhí)行的,注意不要使代碼過(guò)于線(xiàn)性化。

async getBooksAndAuthor(authorId) {  
    const books = await bookModel.fetchAll();  
    const author = await authorModel.fetch(authorId);  
    return {    
        author,    
        books: books.filter(book => book.authorId === authorId),  
    };
}

這段代碼看起來(lái)邏輯上沒(méi)有問(wèn)題。然而是不正確的。

await bookModel.fetchAll() 將會(huì)等待 fetchAll() 執(zhí)行完。

然后 await authorModel.fetch(authorId) 才會(huì)被執(zhí)行

注意, authorModel.fetch(authorId) 并不依賴(lài) bookModel.fetchAll() 的結(jié)果,實(shí)際上他們可以并行執(zhí)行。然而,由于使用了 await 這兩次調(diào)用就變成了串行的了,花費(fèi)的總時(shí)間將會(huì)遠(yuǎn)超并行的方式。

以下是正確的使用方式:

async getBooksAndAuthor(authorId) {  
    const bookPromise = bookModel.fetchAll();  
    const authorPromise = authorModel.fetch(authorId);  
    const book = await bookPromise;  
    const author = await authorPromise;  
    return {    
        author,    
        books: books.filter(book => book.authorId === authorId),  
    };
}

或者更復(fù)雜的情況下,如果你想依次請(qǐng)求一個(gè)列表的內(nèi)容,你必須依賴(lài) promises:

async getAuthors(authorIds) {  
    // WRONG, this will cause sequential calls 
    // const authors = _.map(  
    //   authorIds,  
    //   id => await authorModel.fetch(id));
// CORRECT  
    const promises = _.map(authorIds, id => authorModel.fetch(id));  
    const authors = await Promise.all(promises);
}

簡(jiǎn)而言之,你必須把這個(gè)工作流程看成是異步的,然后再?lài)L試使用 await 以同步的方式去編寫(xiě)代碼。在復(fù)雜的流程下面,直接使用 promises 可能會(huì)更簡(jiǎn)單。

錯(cuò)誤處理

使用 promises 的情況下,一個(gè)異步函數(shù)會(huì)返回兩種可能的值:resolved 和 rejected。我們可以使用 .then() 來(lái)處理正常的情況 .catch() 處理異常情況。然而對(duì)于 async/await 來(lái)說(shuō),異常處理可能會(huì)有點(diǎn)詭異。

try...catch

最標(biāo)準(zhǔn)的(也是我推薦的)處理方式是使用 try...catch 表達(dá)式。當(dāng) await 一個(gè)函數(shù)調(diào)用的時(shí)候,任何 rejected 的值都會(huì)以異常的形式拋出來(lái)。這里有個(gè)例子:

class BookModel {  
    fetchAll() {    
        return new Promise((resolve, reject) => {      
            window.setTimeout(() => { 
                reject({"error": 400}) 
            }, 1000);    
        });  
    }
}
// async/await
async getBooksByAuthorWithAwait(authorId) {
    try {  
        const books = await bookModel.fetchAll();
    } catch (error) {  
        console.log(error);    // { "error": 400 }
    }
}

被捕獲的錯(cuò)誤就是 rejected 的值。在我們捕獲這個(gè)異常之后,我們有很多方式來(lái)處理它:

處理掉這個(gè)異常,然后返回一個(gè)正常的值。(沒(méi)有在 catch 塊中使用任何 return 表達(dá)式等價(jià)于使用 return undefined ;同時(shí),返回的仍是一個(gè) resolved 的值。)

拋出這個(gè)異常,如果你希望調(diào)用者去處理它。你可以直接拋出原始的錯(cuò)誤對(duì)象,例如 throw error; ,這種方式允許你以 promise 鏈?zhǔn)降姆绞绞褂? async getBooksByAuthorWithAwait() 方法(列如,你仍然可以像 getBooksByAuthorWithAwait().then(...).catch(error => ...) 這樣調(diào)用它);或者,你可以使用 Error 對(duì)象包裝錯(cuò)誤對(duì)象,例如, throw new Error(error) ,使用這種方式可以在控制臺(tái)中展示所有的調(diào)用棧記錄。

使用 Reject,例如, return Promise.reject(error) ,這個(gè)方式等價(jià)于 throw error ,因此不推薦使用這種方式。

使用 try...catch 的優(yōu)點(diǎn)有以下這些:

簡(jiǎn)單,傳統(tǒng)。只要你有其他語(yǔ)言的經(jīng)驗(yàn),例如 C++ 或 Java,理解這種處理方式將不會(huì)有任何困難。

你可以將多個(gè) await 調(diào)用包裝在一個(gè) try...catch 塊中來(lái)集中處理所有錯(cuò)誤,如果每一步的錯(cuò)誤處理非必要的話(huà)。

這種處理方式有一個(gè)缺陷。由于 try...catch 將會(huì)捕獲這個(gè)代碼塊中的所有異常,一些其他通常不會(huì)被 promises 捕獲的異常也會(huì)被捕獲住。考慮一下這個(gè)例子:

class BookModel {  
    fetchAll() {    
        cb();    // note `cb` is undefined and will result an exception    
        return fetch("/books");  
    }
}
try {  
    bookModel.fetchAll();
} catch(error) {  
    console.log(error);  // This will print "cb is not defined"
}

執(zhí)行這段代碼你將會(huì)在控制臺(tái)中得到一個(gè)錯(cuò)誤: ReferenceError: cb is not defined ,這些文字是黑色的。這個(gè)錯(cuò)誤是 console.log() 打印出來(lái)的而不是 JavaScript 自身。某些時(shí)候這將會(huì)是致命的:如果 BookModel 被一系列函數(shù)調(diào)用深深地封閉起來(lái)了,同時(shí),其中某一個(gè)調(diào)用將這個(gè)錯(cuò)誤處理掉了,這時(shí)候就很難像這樣去發(fā)現(xiàn)這個(gè)錯(cuò)誤了。

使函數(shù)同時(shí)返回兩個(gè)值

另外一個(gè)錯(cuò)誤處理的方式是由 Go 語(yǔ)言啟發(fā)的。它允許 async 函數(shù)同時(shí)返回錯(cuò)誤的值和正常的值??梢詮南旅孢@個(gè)博客中了解到更詳細(xì)的的介紹:

[How to write async await without try-catch blocks in Javascript
ES7 Async/await allows us as developers to write asynchronous JS code that look synchronous. In current JS version we…blog.grossman.io](https://blog.grossman.io/how-...

簡(jiǎn)而言之,你能夠像下面這樣使用 async 函數(shù):

[err, user] = await to(UserModel.findById(1));

我個(gè)人并不喜歡這種處理方式,因?yàn)樗?Go 語(yǔ)言的編程風(fēng)格帶到了 JavaScript 中,這樣顯得不自然,但是在某些情況下這種方式會(huì)很有用。

使用 .catch

我要介紹的最后一種處理方式是仍然使用 .catch()

回憶一下 await 的功能:它會(huì)等待一個(gè) promise 完成它的任務(wù)。同時(shí)請(qǐng)回憶一下, promise.catch() 也會(huì)返回一個(gè) promise!因此我們可以像下面這樣處理錯(cuò)誤處理的方式:

// books === undefined if error happens,
// since nothing returned in the catch statement
let books = await bookModel.fetchAll()  
    .catch((error) => { 
        console.log(error); 
    });

這種處理方式有兩個(gè)次要的問(wèn)題:

這種方式混合了 promises 和 async 函數(shù)。你仍然需要理解 promises 的運(yùn)行原理之后才能讀懂它。

錯(cuò)誤處理在正常流程之前,這樣是不太直觀的。

結(jié)論

在 ES7 中引入的 async/await 關(guān)鍵字無(wú)疑是對(duì) JavaScript 異步編程的一大加強(qiáng)。它能夠把代碼變得更易于閱讀和調(diào)試。然后,為了正確的使用它們,必須要完全理解 promises,因?yàn)樗鼈儾贿^(guò)是語(yǔ)法糖,底層的技術(shù)仍然是 promises。

希望這篇文章能夠給你一些關(guān)于 async/await 的啟發(fā),同時(shí)能夠幫助你避免一些常見(jiàn)的錯(cuò)誤。感謝閱讀,如果喜歡的話(huà),請(qǐng)為我點(diǎn)贊。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/104984.html

相關(guān)文章

  • JSON應(yīng)知應(yīng)會(huì)

    摘要:兩種格式對(duì)象對(duì)象是一個(gè)無(wú)序的名稱(chēng)值對(duì)集合。數(shù)組數(shù)組是值的有序集合。值之間使用逗號(hào)分隔。這兩個(gè)方法分別用于把對(duì)象序列化為字符串和把字符串解析為原生值方法用于將字符串轉(zhuǎn)化成對(duì)象對(duì)應(yīng)的表示利用將對(duì)象轉(zhuǎn)換成字符串 JSON簡(jiǎn)介 簡(jiǎn)介:JSON(JavaScriptObject Notation)、輕量級(jí)數(shù)據(jù)交換格式、非常適合于服務(wù)器與 JavaScript 的交互。 JSON兩種格式: 1、對(duì)...

    Flink_China 評(píng)論0 收藏0
  • JSON應(yīng)知應(yīng)會(huì)

    摘要:兩種格式對(duì)象對(duì)象是一個(gè)無(wú)序的名稱(chēng)值對(duì)集合。數(shù)組數(shù)組是值的有序集合。值之間使用逗號(hào)分隔。這兩個(gè)方法分別用于把對(duì)象序列化為字符串和把字符串解析為原生值方法用于將字符串轉(zhuǎn)化成對(duì)象對(duì)應(yīng)的表示利用將對(duì)象轉(zhuǎn)換成字符串 JSON簡(jiǎn)介 簡(jiǎn)介:JSON(JavaScriptObject Notation)、輕量級(jí)數(shù)據(jù)交換格式、非常適合于服務(wù)器與 JavaScript 的交互。 JSON兩種格式: 1、對(duì)...

    lijy91 評(píng)論0 收藏0
  • Babel 配置工程師應(yīng)知應(yīng)會(huì)

    摘要:,標(biāo)題黨了,本文僅介紹相關(guān)生態(tài)和一些配置心得。函數(shù)是在時(shí)候常用的工具函數(shù),對(duì)編譯模塊時(shí),會(huì)將用到的放到模塊頂部。用來(lái)看最終引入了哪些必須配合,貌似加入了此項(xiàng)以后,會(huì)得到類(lèi)似于的效果。 Babel Sorry,標(biāo)題黨了,本文僅介紹 Babel 相關(guān)生態(tài)和一些配置心得。 Babel 各個(gè) package 的用途 babel-core: 核心部分 babel-cli: 允許使用命令行 ...

    caikeal 評(píng)論0 收藏0
  • 應(yīng)知應(yīng)會(huì)】15個(gè)常用的JavaScript字符串操作方法

    摘要:輸出和字符串大小寫(xiě)轉(zhuǎn)換方法,和是針對(duì)特定地區(qū)的實(shí)現(xiàn)。輸出輸出輸出輸出基于指定的分割符將一個(gè)字符串分割成多個(gè)子串。 1 初始化 //常用初始化方法 var stringVal = hello iFat3; //構(gòu)造函數(shù)創(chuàng)建方法 var stringObj = new String(hello iFag3); 2 length屬性 var stringVal = hello iFat3; ...

    wwq0327 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<