記錄 Promise 的方法

来源:https://www.cnblogs.com/chenmijiang/archive/2023/04/13/17314754.html
-Advertisement-
Play Games

Promise 是非同步編程的一種解決方案,比傳統的回調函數或事件更合理和更靈活。 Promise 方法 Promise的原型方法:then/catch/finally,這三種方法很常用,then用於處理Promise轉為fulfilled狀態時的代碼,catch用於處理Promise轉為reject ...


Promise 是非同步編程的一種解決方案,比傳統的回調函數或事件更合理和更靈活。

Promise 方法

Promise的原型方法:then/catch/finally,這三種方法很常用,then用於處理Promise轉為fulfilled狀態時的代碼,catch用於處理Promise轉為rejected狀態時的代碼(當然then的第二個參數也可處理rejected狀態),而finally用於不管Promise狀態怎樣轉換都會最終執行的代碼。

promise的then方法的第二個參數和catch方法都可以處理rejected狀態,但它們之間有一些區別:

  1. then的第二個參數只能處理當前的promise,而catch方法可以處理任意位置的rejected狀態。所以,如果多個then方法鏈式調用中有多個rejected狀態,可以在最後使用一個catch方法來處理。

  2. then的第二個參數和catch方法的返回值不同。then的第二個參數返回的是一個新的promise對象,而catch方法返回的是一個值或一個新的promise對象。如果返回的是一個值,則會被自動包裝成一個resolved狀態的promise。

  3. catch方法比then的第二個參數更簡潔,更易讀。因為catch方法只處理rejected狀態,而then方法需要在第一個參數中同時處理resolved和rejected狀態。

Promise的靜態方法: Promise.all、Promise.allSettled、Promise.any、Promise.race、Promise.resolve、Promise.reject。

Promise 靜態方法

Promise.resolve和Promise.reject用於一開始就創建 fulfilledrejected狀態的Promise,其他的靜態方法傳參是Promise實例數組,差異在於處理實例數組的方式和結果。

Promise.all

並行執行多個Promise對象,併在所有Promise對象都成功時返回一個新的Promise對象,其resolve值為一個包含所有Promise結果的數組,如果其中一個Promise對象失敗,則返回一個reject的Promise對象,其值為第一個失敗的Promise的reject值

;(async () => {
  const promise1 = Promise.resolve('Hello')
  const promise2 = 42
  // const promise2 = Promise.reject('Error')
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'Goodbye')
  })
  // const promise4 = Promise.reject('Error2')

  try {
    const result = await Promise.all([promise1, promise2, promise3])
    // 成功輸出:[ 'Hello', 42, 'Goodbye' ]
    console.log(result)
  } catch (e) {
    // 失敗輸出:Error
    console.log(e)
  }
})()

Promise.allSettled

並行執行多個Promise對象,返回一個新的Promise對象(狀態一定是fulfilled),其resolve值為一個包含所有Promise結果的數組,其中每個元素都是對象,包含Promise對象的狀態和結果

;(async () => {
  const promise1 = Promise.resolve('Hello')
  const promise2 = 42
  // const promise2 = Promise.reject('Error')
  const promise3 = new Promise((resolve, reject) => {
    setTimeout(resolve, 1000, 'Goodbye')
  })
  // const promise4 = Promise.reject('Error2')

  try {
    const result = await Promise.allSettled([promise1, promise2, promise3])
    // 成功輸出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'fulfilled', value: 42 },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
    console.log(result)
    // 失敗輸出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'rejected', reason: 'Error' },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
  } catch(e) {
    // 不會執行
      console.log('error:', e)
  }

  Promise.allSettled([promise1, promise2, promise3]).then((result) => {
    // 成功輸出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'fulfilled', value: 42 },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
    console.log(result)
    // 失敗輸出:
    // [
    //   { status: 'fulfilled', value: 'Hello' },
    //   { status: 'rejected', reason: 'Error' },
    //   { status: 'fulfilled', value: 'Goodbye' }
    // ]
  })
})()

Promise.all和Promise.allSettled的區別:

  1. Promise.all方法返回的一個Promise對象狀態將取決於所有Promise對象的狀態。如果其中有任何一個Promise對象被rejected了,那麼這個新的Promise對象也會被rejected,並且它的值為第一個被rejected的那個Promise對象的值。
  2. Promise.allSettled方法返回的一個Promise對象狀態一定是fulfilled。這個返回的Promise對象的值是一個數組,數組中包含了所有Promise對象的狀態和值信息。即便其中有任何一個Promise對象被rejected了,也不會影響這個新的Promise對象的狀態。
  3. 錯誤處理方面,Promise.all只能捕獲處理第一個錯誤狀態,如果需要處理所有狀態需要改造(如:每個promise設置catch處理、同步請求/非同步等待)或者使用 Promise.allSettled,具體需要怎麼做看自己的需求

Promise.any

並行執行多個Promise對象,並返回一個新的Promise對象,其resolve值為第一個成功的Promise對象的resolve值,如果所有Promise對象都失敗,則返回一個reject的Promise對象,其值為一個AggregateError對象,其中包含所有Promise對象的reject值。

const promise1 = Promise.reject("error1")
const promise2 = Promise.reject("error2")
const promise3 = Promise.resolve("success")
// const promise3 = Promise.reject("error3")

Promise.any([promise1, promise2, promise3]).then((value) => {
  // 成功輸出:success
  console.log(value)
}).catch((error) => {
  // 失敗輸出:
  // [AggregateError: All promises were rejected] {
  //   [errors]: [ 'error1', 'error2', 'error3' ]
  // }
  console.log(error)
})

Promise.race

並行執行多個Promise對象,並返回一個新的Promise對象,其resolve值為第一個完成的Promise對象的resolve值,如果所有Promise對象都失敗,則返回一個reject的Promise對象,其值為第一個失敗的Promise的reject值。

const promise1 = Promise.reject("error1")
const promise2 = Promise.reject("error2")
const promise3 = Promise.resolve("success")
// const promise3 = Promise.reject("error3")

Promise.race([promise1, promise2, promise3]).then((value) => {
  // 成功輸出:error1
  console.log(value)
}).catch((error) => {
  // 失敗輸出:error1
  console.log(error)
})

Promise.race和Promise.any的區別:

  1. Promise.race會在其中任意一個Promise對象狀態改變(即fulfilled或rejected)時立即返回結果,而Promise.any只會在其中任意一個Promise對象fulfilled時返回結果。

  2. 當所有Promise對象都被rejected時,Promise.race會返回被rejected的Promise對象的結果,而Promise.any會拋出AggregateError異常。

  3. 如果Promise.race傳入的參數是空數組,它會一直處於pending狀態,而Promise.any會立即拋出AggregateError異常。(另外:Promise.all和Promise.allSettled返回fulfilled狀態)

使用Promise實現站點預檢

這是前幾天實現的站點預檢:判斷所有網站鏈接是否有效,並返回測試的結果。思路:通過get請求測試,考慮請求之間沒有關聯、錯誤處理方面最終選擇Promise.allSettled,代碼如下:

// 實現 對多個網站鏈接預檢,判定網站鏈接是否有效

import { get } from 'https'
import { get as getHttp } from 'http'
import { URL } from 'url'

import { ATagSites } from '@/type'

export const detectSitesValid = (allSites: ATagSites[]) => {
  // 遍歷 allSites 數組,獲取所有網站的鏈接
  const sites: { name: string; url: string }[] = []
  allSites.forEach((aTagSites) => {
    aTagSites.sites.forEach((site) => {
      sites.push({
        name: site.name,
        url: site.link
      })
    })
  })

  // 存儲所有網站的請求
  const fetchRequests: Promise<string>[] = []
  // 存儲請求結果
  const fetchResults: string[] = []

  // 遍歷所有網站,發起請求
  sites.forEach((site) => {
    const { name, url } = site
    const { protocol } = new URL(url)
    const request = protocol === 'https:' ? get : getHttp
    fetchRequests.push(
      new Promise((resolve, reject) => {
        request(
          {
            hostname: new URL(url).hostname,
            path: new URL(url).pathname,
            method: 'GET',
            timeout: 30000
          },
          (res) => {
            const { statusCode, statusMessage } = res
            fetchResults.push(`${name}, ${url}, ${statusCode || 200}, ${statusMessage || 'OK'}`)
            resolve('ok')
          }
        ).on('error', (err) => {
          const { message } = err
          fetchResults.push(`${name}, ${url}, ${0}, ${message}`)
          resolve('error')
        })
      })
    )
  })

  return Promise.allSettled(fetchRequests)
}

參考


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Redis是一個開源的,基於記憶體的,高性能的鍵值型資料庫。它支持多種數據結構,包含五種基本類型 String(字元串)、Hash(哈希)、List(列表)、Set(集合)、Zset(有序集合),和三種特殊類型 Geo(地理位置)、HyperLogLog(基數統計)、Bitmaps(點陣圖),可以滿足各... ...
  • 4月22日下午14:00,雲資料庫技術和NineData主辦的「MySQL x ClickHouse」技術沙龍,將在杭州市海智中心3號樓1102報告廳舉辦。本次沙龍以“技術進化,讓數據更智能”為主題,匯聚位元組跳動、阿裡雲、玖章算術、華為雲、騰訊雲等眾多資料庫廠商的技術大咖, 圍繞MySQL x Cl... ...
  • 新媒體時代,廣告樣式越來越豐富。相較於傳統的圖文信息,視頻類廣告更具有直觀性,能夠讓消費者在瞭解產品知識和功能的同時加深對產品的印象。 因此在各類網站或App上投放視頻類廣告是個很好的宣傳方式,但廣告商們如果想在網站上展示視頻廣告,必須確保視頻廣告投放協議與發佈渠道的播放器相容;如果不能相容,廣告商 ...
  • ChatBox 是什麼 開源的 ChatGPT API (OpenAI API) 桌面客戶端,Prompt 的調試與管理工具,支持 Windows、Mac 和 Linux。 為什麼需要它 每次想訪問 ChatGPT 時,都需要在瀏覽器中輸入 ChatGPT 網址,然後點擊登錄,選擇賬號,整個過程中比 ...
  • 今天解決了我自認為一個很不起眼的Bug。 我的Tabs下麵有5個tabPane,並且這幾個tabPane共用了一個search組件,今天遇到了一個bug,就是這幾個組件使用公共查找組件的時候,前一個組件的值會影響下一個組件的值。 找了半天發現,原來我應該在父組件Tabs中定義一個useState的狀 ...
  • 項目忙完,這次上新,寫一個前端系列,採用vue3來開發一個微信公眾號商城。 前言: 1. 微信公眾號商城本質也是一個網站,由一個個網頁組成,只不過這些網頁運行在手機端,能響應手指的點擊、長按、拖拽等操作。 2. 既然是網頁,當然可以用3件套(js+html+css)來寫,但象vue這樣的前端框架比3 ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前言 平時在使用v-for的時候,一般會要求傳入key,有沒有像我一樣的小伙伴,為了省心,直接傳索引index,貌似也沒有遇到過什麼問題,直到有一天,我遇到一個這樣的需求 場景 在一個下單界面,我需要去商品列表選商品,然後在下單界面遍歷顯 ...
  • 前端模板 - Anchor UI KIT 前言 今天介紹一款製作精良、開源、免費的 Bootstrap 模板 —— Anchor UI KIT 該模板使用的是Bootstrap v4版本 本文將介紹如何在Django中導入該模板的靜態資源包並使用 介紹 官方文檔 Anchor - a free Bo ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...