首頁 web前端 js教程 js非同步回呼Async/Await與Promise的區別,Async/Await取代Promise的6個理由

js非同步回呼Async/Await與Promise的區別,Async/Await取代Promise的6個理由

Sep 12, 2018 pm 04:45 PM
js promise

本章跟大家介紹js非同步回調Async/Await與Promise的差別,Async/Await取代Promise的6個理由。有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

什麼是Async/Await?

#async/await是寫非同步程式碼的新方式,先前的方法有回呼函數和Promise。

async/await是基於Promise實現的,它不能用於普通的回呼函數。

async/await與Promise一樣,是非阻塞的。

async/await使得非同步程式碼看起來像同步程式碼,這正是它的魔力所在。

Async/Await語法

範例中,getJSON函數回傳一個promise,這個promise成功resolve時會回傳一個JSON物件。我們只是呼叫這個函數,印出返回的JSON對象,然後返回"done"。

使用Promise是這樣的:

const makeRequest = () =>
  getJSON()
    .then(data => {
      console.log(data)
      return "done"
    })makeRequest()
登入後複製

使用Async/Await是這樣的:

const makeRequest = async () => {
  console.log(await getJSON())
  return "done"}makeRequest()
登入後複製

它們有一些細微不同:

函數前面多了一個aync關鍵字。 await關鍵字只能用在aync定義的函數內。 async函數會隱式地回傳一個promise,該promise的reosolve值就是函數return的值。 (範例中reosolve值就是字串"done")

第1點暗示我們不能在最外層程式碼中使用await,因為不在async函數內。

// 不能在最外层代码中使用
awaitawait makeRequest()
// 这是会出事情的 
makeRequest().then((result) => {
  // 代码
 })
登入後複製

await getJSON()表示console.log會等到getJSON的promise成功reosolve之後再執行。

為什麼Async/Await比較好?

1. 簡潔

由範例可知,使用Async/Await明顯節約了不少程式碼。我們不需要寫.then,不需要寫匿名函數處理Promise的resolve值,也不需要定義多餘的data變量,還避免了嵌套程式碼。這些小的優點會迅速累積起來,這在之後的程式碼範例中會更加明顯。

2. 錯誤處理

Async/Await讓try/catch可以同時處理同步和非同步錯誤。在下面的promise範例中,try/catch不能處理JSON.parse的錯誤,因為它在Promise中。我們需要使用.catch,這樣錯誤處理程式碼非常冗餘。並且,在我們的實際生產程式碼會更加複雜。

const makeRequest = () => {
  try {
    getJSON()
      .then(result => {
        // JSON.parse可能会出错
        const data = JSON.parse(result)
        console.log(data)
      })
      // 取消注释,处理异步代码的错误
      // .catch((err) => {
      //   console.log(err)
      // })
  } catch (err) {
    console.log(err)
  }}
登入後複製

使用aync/await的話,catch能處理JSON.parse錯誤:

const makeRequest = async () => {
  try {
    // this parse may fail
    const data = JSON.parse(await getJSON())
    console.log(data)
  } catch (err) {
    console.log(err)
  }}
登入後複製

3. 條件語句

下面範例中,需要取得數據,然後根據傳回數據決定是直接返回,還是繼續取得更多的數據。 ·

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層),括號,return語句很容易讓人感到迷茫,而它們只是需要將最終結果傳遞到最外層的Promise。

上面的程式碼使用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    
  }}
登入後複製

4. 中間值

你很可能遇到過這樣的場景,調用promise1,使用promise1回傳的結果去呼叫promise2,然後使用兩者的結果去呼叫promise3。你的程式碼很可能是這樣的:

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return promise2(value1)
        .then(value2 => {        
          return promise3(value1, value2)
        })
    })}
登入後複製

如果promise3不需要value1,可以很簡單地將promise巢狀鋪平。如果你忍受不了嵌套,你可以將value 1 & 2 放進Promise.all來避免深層嵌套:

const makeRequest = () => {
  return promise1()
    .then(value1 => {
      return Promise.all([value1, promise2(value1)])
    })
    .then(([value1, value2]) => {      
      return promise3(value1, value2)
    })}
登入後複製

這種方法為了可讀性犧牲了語意。除了避免嵌套,並沒有其他理由將value1和value2放在一個陣列中。

使用async/await的話,程式碼會變得異常簡單和直覺。

const makeRequest = async () => {
  const value1 = await promise1()
  const value2 = await promise2(value1)
  return promise3(value1, value2)}
登入後複製

5. 錯誤堆疊

下面範例中呼叫了多個Promise,假設Promise鏈中某個地方拋出了一個錯誤:

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)
  })
登入後複製

Promise鏈中返回的錯誤棧沒有給出錯誤發生位置的線索。更糟的是,它會誤導我們;錯誤堆疊中唯一的函數名為callAPromise,然而它和錯誤沒有關係。 (檔名和行號還是有用的)。

然而,async/await中的錯誤堆疊會指向錯誤所在的函數:

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)
  })
登入後複製

在開發環境中,這一點優勢並不大。但是,當你分析生產環境的錯誤日誌時,它將非常有用。這時,知道錯誤發生在makeRequest比知道錯誤發生在then鏈中要好。

6. 偵錯

最後一點,也是非常重要的一點在於,async/await能夠讓程式碼偵錯更簡單。 2個理由使得偵錯Promise變得非常痛苦:

1)不能在返回表達式的箭頭函數中設定斷點 

js非同步回呼Async/Await與Promise的區別,Async/Await取代Promise的6個理由

2)如果你在.then程式碼區塊中設定斷點,使用Step Over快捷鍵,偵錯器不會跳到下一個.then,因為它只會跳過非同步程式碼。

使用await/async時,你不再需要那麼多箭頭函數,這樣你就可以像調試同步程式碼一樣跳過await語句

js非同步回呼Async/Await與Promise的區別,Async/Await取代Promise的6個理由

結論

Async/Await是近年來JavaScript添加的最革命性的特性之一。它會讓你發現Promise的語法有多糟糕,而且提供了一個直覺的替代方法。

憂慮

#

對於Async/Await,也許你有一些合理的懷疑:
   它使得非同步程式碼不在明顯: 我們已經習慣了用回調函數或.then來識別非同步程式碼,我們可能需要花數個星期去習慣新的標誌。但是,C#擁有這個特性已經很多年了,熟悉它的朋友應該知道暫時的稍微不方便是值得的。
   Node 7不是LTS(長期支援版本): 但是,Node 8下個月就會發布,將程式碼遷移到新版本會非常簡單。

以上是js非同步回呼Async/Await與Promise的區別,Async/Await取代Promise的6個理由的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

建議:優秀JS開源人臉偵測辨識項目 建議:優秀JS開源人臉偵測辨識項目 Apr 03, 2024 am 11:55 AM

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

如何使用JS和百度地圖實現地圖平移功能 如何使用JS和百度地圖實現地圖平移功能 Nov 21, 2023 am 10:00 AM

如何使用JS和百度地圖實現地圖平移功能百度地圖是一款廣泛使用的地圖服務平台,在Web開發中經常用於展示地理資訊、定位等功能。本文將介紹如何使用JS和百度地圖API實作地圖平移功能,並提供具體的程式碼範例。一、準備工作使用百度地圖API前,首先需要在百度地圖開放平台(http://lbsyun.baidu.com/)上申請一個開發者帳號,並建立一個應用程式。創建完成

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 Dec 17, 2023 pm 06:55 PM

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟,需要具體程式碼範例隨著網路和科技的快速發展,股票交易已成為許多投資者的重要途徑之一。而股票分析是投資人決策的重要一環,其中蠟燭圖被廣泛應用於技術分析。學習如何使用PHP和JS繪製蠟燭圖將為投資者提供更多直觀的信息,幫助他們更好地做出決策。蠟燭圖是一種以蠟燭形狀來展示股票價格的技術圖表。它展示了股票價格的

如何使用PHP和JS創建股票蠟燭圖 如何使用PHP和JS創建股票蠟燭圖 Dec 17, 2023 am 08:08 AM

如何使用PHP和JS創建股票蠟燭圖股票蠟燭圖是股票市場中常見的技術分析圖形,透過繪製股票的開盤價、收盤價、最高價和最低價等數據,幫助投資者更直觀地了解股票的價格波動情形。本文將教你如何使用PHP和JS創建股票蠟燭圖,並附上具體的程式碼範例。一、準備工作在開始之前,我們需要準備以下環境:1.一台運行PHP的伺服器2.一個支援HTML5和Canvas的瀏覽器3

如何使用JS和百度地圖實現地圖點擊事件處理功能 如何使用JS和百度地圖實現地圖點擊事件處理功能 Nov 21, 2023 am 11:11 AM

如何使用JS和百度地圖實現地圖點擊事件處理功能概述:在網路開發中,經常需要使用地圖功能來展示地理位置和地理資訊。而地圖上的點擊事件處理是地圖功能中常用且重要的一環。本文將介紹如何使用JS和百度地圖API來實現地圖的點擊事件處理功能,並給出具體的程式碼範例。步驟:匯入百度地圖的API檔案首先,要在HTML檔案中匯入百度地圖API的文件,可以透過以下程式碼實現:

言出必行:兌現承諾的好處和壞處 言出必行:兌現承諾的好處和壞處 Feb 18, 2024 pm 08:06 PM

在日常生活中,我們常常會遇到承諾與兌現之間的問題。無論是在個人關係中,或是在商業交易中,承諾的兌現都是建立信任的關鍵。然而,承諾的利與弊也常常會引起爭議。本文將探討承諾的利與弊,並給予一些建議,如何做到言出必行。承諾的利是顯而易見的。首先,承諾可以建立信任。當一個人信守承諾時,他會讓別人相信自己是個可信賴的人。信任是人與人之間建立的紐帶,它可以讓人們更加

如何使用JS和百度地圖實現地圖熱力圖功能 如何使用JS和百度地圖實現地圖熱力圖功能 Nov 21, 2023 am 09:33 AM

如何使用JS和百度地圖實現地圖熱力圖功能簡介:隨著互聯網和行動裝置的快速發展,地圖成為了普遍的應用場景。而熱力圖作為一種視覺化的展示方式,能夠幫助我們更直觀地了解數據的分佈。本文將介紹如何使用JS和百度地圖API來實現地圖熱力圖的功能,並提供具體的程式碼範例。準備工作:在開始之前,你需要準備以下事項:一個百度開發者帳號,並建立一個應用,取得到對應的AP

PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 Dec 18, 2023 pm 03:39 PM

隨著網路金融的快速發展,股票投資已經成為了越來越多人的選擇。而在股票交易中,蠟燭圖是常用的技術分析方法,它能夠顯示股票價格的變動趨勢,幫助投資人做出更精準的決策。本文將透過介紹PHP和JS的開發技巧,帶領讀者了解如何繪製股票蠟燭圖,並提供具體的程式碼範例。一、了解股票蠟燭圖在介紹如何繪製股票蠟燭圖之前,我們首先需要先了解什麼是蠟燭圖。蠟燭圖是由日本人

See all articles