日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ES2017 异步函数async/await

發布時間:2024/1/23 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ES2017 异步函数async/await 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

ES2017標準已于2017年6月份正式定稿了,并廣泛支持最新的特性:異步函數。如果你曾經被異步 JavaScript 的邏輯困擾,這么新函數正是為你設計的。

異步函數或多或少會讓你編寫一些順序的 JavaScript 代碼,但是卻不需要在 callbacks、generators 或 promise 中包含你的邏輯。

如下代碼:

function logger() {

????let data = fetch('http://sampleapi.com/posts')

????console.log(data)

}

logger()

這段代碼并未實現你的預期。如果你是在JS中編寫的,那么你可能會知道為什么。

下面這段代碼,卻實現了你的預期。

async function logger() {

????let data = await fetch('http:sampleapi.com/posts')

????console.log(data)

}

logger()

這段代碼起作用了,從直觀上看,僅僅只是多了 async 和 await 兩個詞。

ES6 標準之前的 JavaScript 異步函數

在深入學習 async 和 await 之前,我們需要先理解 Promise。為了領會 Promise,我們需要回到普通回調函數中進一步學習。

Promise 是在 ES6 中引入的,并促使在編寫 JavaScript 的異步代碼方面,實現了巨大的提升。從此編寫回調函數不再那么痛苦。

回調是一個函數,可以將結果傳遞給函數并在該函數內進行調用,以便作為事件的響應。同時,這也是JS的基礎。

function readFile('file.txt', (data) => {

????// This is inside the callback function

????console.log(data)

}

這個函數只是簡單的向文件中記錄數據,在文件完成之前進行讀取是不可能的。這個過程似乎很簡單,但是如果想要按順序讀取并記錄五個不同的文件,需要怎么實現呢?

沒有 Promise 的時候,為了按順序執行任務,就需要通過嵌套回調來實現,就像下面的代碼:

// This is officially callback hell

function combineFiles(file1, file2, file3, printFileCallBack) {

????let newFileText = ''

????readFile(string1, (text) => {

????????newFileText += text

????????readFile(string2, (text) => {

????????????newFileText += text

????????????readFile(string3, (text) => {

????????????????newFileText += text

????????????????printFileCallBack(newFileText)

????????????}

????????}

????}

}

這就很難推斷函數下面會發生什么,同時也很難處理各種場景下發生的錯誤,比如其中某個文件不存在的情況。

Promise 改善了這種情況

這正是 Promise 的優勢所在,Promise 是對還未產生的數據的一種推理。Kyle Simpson 將 Promise 解釋為:就像在快餐店里點餐一樣。

  • 點餐

  • 為所點的午餐付費,并拿到排隊單號

  • 等待午餐

  • 當你的午餐準備好了,會叫你的單號提醒你取餐

  • 收到午餐

正如上面的這種場景,當你等餐時,你是無法吃到午餐的,但是你可以提前為吃午餐做好準備。你可以進行其它事情,此時你知道午餐就要來了,雖然此刻你還無法享用它,但是這個午餐已經“promise”給你了。這就是所謂的 promise,表示一個最終會存在的數據的對象。

readFile(file1)

????.then((file1-data) => { /* do something */ })

????.then((previous-promise-data) => { /* do the next thing */ })

????.catch( /* handle errors */ )


上面是 Promise 語法。它主要的優點就是可以將隊列事件以一種直觀的方式鏈接在一起。雖然這個示例清晰易懂,但是還是用到了回調。Promise 只是讓回調顯得比較簡單和更加直觀。

最佳方式:async / await

若干年前,async 函數納入了 JavaScript 生態系統。就在上個月,async 函數成為了 JavaScript 語言的官方特性,并得到了廣泛支持。

async 和 await 是建立在 Promise 和 generator上。本質上,允許我們使用 await 這個關鍵詞在任何函數中的任何我們想要的地方進行暫停。

async function logger() {

????// pause until fetch returns

????let data = await fetch('http://sampleapi.com/posts')

????console.log(data)

}

上面這段代碼運行之后,得到了想要的結果。代碼從 API 調用中記錄了數據。

這種方式的好處就是非常直觀。編寫代碼的方式就是大腦思考的方式,告訴腳本在需要的地方暫停。

另一個好處是,當我們不能使用 promise 時,還可以使用 try 和 catch:

async function logger ()??{

????try {

????????let user_id = await fetch('/api/users/username')

????????let posts = await fetch('/api/`${user_id}`')

????????let object = JSON.parse(user.posts.toString())

????????console.log(posts)

????} catch (error) {

????????console.error('Error:', error)

????}

}

上面是一個刻意寫錯的示例,為了證明了一點:在運行過程中,catch 可以捕獲任何步驟中發生的錯誤。至少有三個地方,try 可能會失敗,這是在異步代碼中的一種最干凈的方式來處理錯誤。

我們還可以使用帶有循環和條件的 async 函數:

async function count() {

????let counter = 1

????for (let i = 0; i ) {

????????counter += 1

????????console.log(counter)

????????await sleep(1000)

????}

}

這是一個很簡答的例子,如果運行這段程序,將會看到代碼在 sleep 調用時暫停,下一個循環迭代將會在1秒后啟動。

要點和細節

相信我們已經感受到了 asyns 和 await 的美妙之處,接下來讓我們深入了解一下細節:

  • async 和 await 建立在 Promise 之上。使用 async,總是會返回一個 Promise。請記住這一點,因為這也是容易犯錯的地方。

  • 當執行到 await 時,程序會暫停當前函數,而不是所有代碼

  • async 和 await 是非阻塞的

  • 依舊可以使用 Promise helpers,例如 Promise.all( )

正如之前的示例:

async function logPosts ()??{

????try {

????????let user_id = await fetch('/api/users/username')

????????let post_ids = await fetch('/api/posts/<code>${user_id}')

????????let promises = post_ids.map(post_id => {

????????????return??fetch('/api/posts/${post_id}')

????????}

????????let posts = await Promise.all(promises)

????????console.log(posts)

????} catch (error) {

????????console.error('Error:', error)

????}

}

  • await 只能用于聲明為 async 的函數中

  • 因此,不能在全局范圍內使用 await

如下代碼:

// throws an error

function logger (callBack) {

????console.log(await callBack)

}

?

// works!

async function logger () {

????console.log(await callBack)

}

現已正式可用

到2017年6月,幾乎所有瀏覽器都可以使用 async 和 await。為了確保你的代碼隨時可用,則需要使用 Babel 將你的 JavaScript 代碼編譯為舊瀏覽器也支持的語法。

總結

以上是生活随笔為你收集整理的ES2017 异步函数async/await的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。