Promise對象

来源:https://www.cnblogs.com/cs-songbai/p/18235139
-Advertisement-
Play Games

Promise 對象使用 ★ Promise 基本認識 Promise 是一個對象,用於表示非同步操作的最終完成(或失敗)及其結果值。它允許你關聯處理程式,這些處理程式將在非同步操作成功完成時或者失敗時調用,從而避免了更複雜的嵌套回調(即回調地獄)。Promise 對象通常用於執行非同步操作,如網路請求、 ...


Promise 對象使用

Promise 基本認識

Promise 是一個對象,用於表示非同步操作的最終完成(或失敗)及其結果值。它允許你關聯處理程式,這些處理程式將在非同步操作成功完成時或者失敗時調用,從而避免了更複雜的嵌套回調(即回調地獄)。Promise 對象通常用於執行非同步操作,如網路請求、文件操作等。它提供了 .then() 和 .catch() 方法來處理 Fulfilled 和 Rejected 狀態的結果。

★ Promise 使用語法

proObj = new Promise((resolved, rejected) => {
        resolved("成功的返回值");
        rejected("失敗的返回值");
    });
proObj
    .then("處理成功情況的回調函數", "處理失敗情況的回調函數")
    .catch("處理 Promise 失敗的情況")

Promise 主要特點

  • 非同步操作的代理:
    一個 Promise 對象代表一個可能還未完成,也可能已經完成的非同步操作。
    
  • 狀態: Promise 對象有三種狀態

    • Pending(進行中):初始狀態,既不是成功,也不是失敗狀態。
    • Fulfilled(已成功):意味著操作成功完成。
    • Rejected(已失敗):意味著操作失敗。
  • 不可變性:

     	Promise的狀態一旦確定,就不會再改變。這意味著一個Promise對象要麼處於pending狀態,要麼處於fulfilled狀態,要麼處於rejected狀態,而且它不會同時處於兩種狀態中。這種不可變性是Promise機制的一個重要特性,它確保了非同步操作的結果一旦確定,就不會因為後續的代碼執行而發生變化.此外,Promise的狀態轉換隻能從pending到fulfilled或從pending到rejected,不能反向轉換。這種單向的狀態轉換機制有助於避免在非同步操作中產生混亂和不可預測的行為
    

Promise 的鏈式調用

  • 說明
    Promise  允許鏈式調用 .then() 方法,每個 .then() 可以返回一個新的 Promise,使得非同步操作可以順序執行。
    
  • 示例
    doSomething()
        .then(function(result) {
            return doSomethingElse(result);
        })
        .then(function(newResult) {
            return doThirdThing(newResult);
        })
        .then(function(finalResult) {
            console.log('Got the final result: ' + finalResult);
        })
        .catch(failureCallback);
    
  • 優點
    • 提供了一種更加優雅的方式來處理非同步操作。
    • 解決了回調地獄問題,使代碼更加清晰和易於維護。
  • 缺點
    • 不能取消 Promise,一旦新建它就會立即執行,無法中途取消。
    • 如果不設置回調函數,Promise 內部拋出的錯誤不會反映到外部。
    • 當處於 Pending 狀態時,無法得知當前進展到哪一個階段(剛開始還是即將完成)。

Promise 應用場景

  • 1-模擬請求數據
    let pro = new Promise(function (resolved, rejected) {
        // 執行非同步操作
        let res = {
            // code: 200,
            // data:{
            //     name:'FL'
            // },
            code: 500,
            error: '伺服器錯誤'
        };
        setTimeout(() => {
            if (res.code === 200) {
                resolved(res.data);
            } else {
                rejected(res.error);
            }
        }, 1000)
    });
    
    
    pro.then((res) => {
        console.log(res);
    }, (error) => {
        console.log(error);
    }).catch(() => console.log('Promise 失敗'));
    
  • 2-封裝超時時間
    function timeOut(ms) {
        return new Promise((resolved, rejected) => {
            setTimeout(() => {
                resolved('hello promise success!!');
            }, ms);
        })
    }
    
    timeOut(2000).then((res) => {
        console.log(res);
    })
    
  • 3-使用promise封裝ajax
    // http://ajax-base-api-t.itheima.net/api/getbooks
    function getJSON(url){
        return new Promise((resolve, reject)=>{
            const xhr = new XMLHttpRequest();
            xhr.open("GET", url);
            // 監控狀態
            xhr.onreadystatechange = handler;
            // 聲明相應數據類型
            xhr.responseType = "json";
            xhr.setRequestHeader('Accept', 'application/json');
            // 發送請求
            xhr.send();
    
            function handler(){
                console.log(this);
                console.log(this.readyState);
                if(this.readyState === 4){
                    if(this.status === 200){
                        resolve(this.response);
                    }else{
                        reject(new Error(this.statusText));
                    }
                }
            }
        })
    }
    
    // then()返回一個新的promise實例,可以採用鏈式編程(將上一級的返回值作為下一級的實參)
    var a = getJSON('http://ajax-base-api-t.itheima.net/api/getbooks')
        .then((data)=>{
            console.log(data);
            // 返回值作為下一級then的實參
            return data.data;
        },(error)=>{
            console.log(error);
        })
        .then((twoStageData)=>{
            console.log(twoStageData);
        });
    console.log(a);
    

then 的第二參數與catch區別

在JavaScript中使用 Promise 時,.then() 方法可以接受兩個參數:第一個是處理成功情況的回調函數,第二個是處理失敗情況的回調函數。而 .catch() 方法則專門用於處理 Promise 失敗的情況。雖然這兩種方式都可以用來處理錯誤,但它們之間存在一些重要的區別:

  • .then() 的第二個參數
    • .then() 的作用

      .then() 方法的第二個參數是一個可選的錯誤處理函數,用於處理 Promise 被拒絕(Rejected)的情況。
      
    • 使用 .then() 的第二個參數處理錯誤有以下特點:

      • 作用域限制:這個錯誤處理函數只捕獲到該 .then() 前面的錯誤,如果在 .then() 的第一個回調函數(處理成功的回調)中發生錯誤,這個錯誤不會被第二個參數捕獲。
      • 鏈式調用:如果 .then() 的第一個回調函數中發生了錯誤,而沒有提供第二個錯誤處理函數,這個錯誤會被傳遞到鏈中下一個 .catch().then() 的第二個參數中。
  • .catch()
    • .catch() 的作用

      .catch() 方法專門用來捕獲鏈中前面任何 Promise 的錯誤。
      promise
          .then(function(value) { /* 處理成功 */ })
          .catch(function(error) { /* 處理所有前面的錯誤 */ });
      
    • 使用 .catch() 的優點包括:

      • 集中處理錯誤.catch() 可以捕獲鏈中前面任何 Promise 的錯誤,包括前面 .then() 中的成功回調里拋出的異常。
      • 提高可讀性:使用 .catch() 可以使得錯誤處理更加集中和明確,代碼更易於理解和維護。
  • 結論
    雖然 .then() 的第二個參數和 .catch() 都可以用來處理錯誤,但推薦使用 .catch(),因為它可以捕獲整個鏈中的錯誤,使得錯誤處理更加集中和清晰。此外,使用 .catch() 也可以避免某些由於遺漏錯誤處理函數而導致的難以追蹤的錯誤。
    

Promise 對象的其他方法

  • resolve() 將現有的任何對象轉換成 Promise 對象
    let p = Promise.resolve('foo');
    // 等價於
    // let p = new Promise(resolve => resolve('foo'));
    console.log(p);
    
    p.then((data)=>{
        console.log(data)});
    
  • all() 多個 Promise 對象運行結果的合併處理
    • 應用說明

      一些游戲類的素材比較多,等待圖片、flash、靜態資源文件都載入完成才進行頁面初始化
      
    • 示例

      let promise1 = new Promise((resolve, reject)=>{});
      let promise2 = new Promise((resolve, reject)=>{});
      let promise3 = new Promise((resolve, reject)=>{});
      
      let p4 =  Promise.all([promise1, promise2, promise3]);
      p4.then(()=>{
          // 三個promise都成功, 才執行
      }).catch((err)=>{
          // 有一個promise失敗, 就執行
      });
      
  • race()
    • 應用說明

      Promise.race() 是一個 JavaScript 方法,它接受一個 Promise 對象的數組作為輸入,並返回一個新的 Promise。這個新的 Promise 將會解決(fulfill)或拒絕(reject)為最先解決或拒絕的輸入 Promise 的結果;Promise.race() 是處理多個非同步操作中最快一個的結果的有效工具。它在需要快速響應的場景或需要處理多個可能的非同步結果時非常有用。
      
    • 使用場景

      • 超時處理:可以與超時邏輯配合使用,比如設置一個時間限制,如果某個操作在指定時間內沒有完成,則自動拒絕。
      • 競爭條件:當多個非同步操作競爭同一個資源時,只需要結果最快的一個。
      • 錯誤恢復:可以啟動多個相同的非同步操作,如果其中一個失敗了,其他的仍然可以繼續,從而提高系統的健壯性。
    • 示例

      // 應用: 監控圖片載入過程, 超過設置的載入時間則停止載入並執行超時處理函數
      function requestImg(imgSrc) {
          return new Promise((resolve, reject)=>{
              // 創建圖片對象
              const img = new Image();
              img.onload = function(){
                  resolve(img);
              };
              img.src = imgSrc
          })
      }
      
      function timeOut(){
          return new Promise((resolve, reject)=>{
              setTimeout(()=>{
                  reject('圖片請求超時!')
              }, 1000);
          })
      }
      
      Promise.race([requestImg('https://img0.baidu.com/it/u=2020518972,2077284106&fm=253&fmt=auto&app=120&f=JPEG?w=889&h=500'), timeOut()])
          .then(res=>{
          console.log('then');
          console.log(res);
          document.body.appendChild(res);
      }).catch(err=>{
          console.log('catch');
          console.log(err);
      })
      
  • done() finally() 不管請求失敗還是成功都會執行的方法

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

-Advertisement-
Play Games
更多相關文章
  • 在Android桌面Launcher源碼淺析中介紹了Android的桌面程式Launcher是如何響應用戶點擊事件並啟動App的,這篇文章繼續介紹App在Android系統層的啟動流程。 一、啟動流程 sequenceDiagram participant User participant Laun ...
  • 前言 容器類庫是指一組用於存儲和管理數據的數據結構和演算法。它們提供了各種不同類型的容器,如數組、鏈表、樹、圖等,以及相關的操作和功能,如查找、插入、刪除、排序等。 容器類庫還可以包含其他數據結構和演算法,如堆、樹、圖等,以及相關的操作和功能,如排序、查找、遍歷等。它們可以用於解決各種不同的問題和場 ...
  • 一、併發 併發是指在一個時間段內,多個事件、任務或操作同時進行或者交替進行的方式。在電腦科學中,特指多個任務或程式同時執行的能力。併發可以提升系統的吞吐量、響應速度和資源利用率,並能更好地處理多用戶、多線程和分散式的場景。常見的併發模型有多線程、多進程、多任務、協程等。 1.併發概述 Ha ...
  • **RDF(資源描述框架)**是一種用於機器理解網路資源的框架,使用XML編寫。它通過URI標識資源,用屬性描述資源,便於電腦應用程式處理信息。RDF在語義網上促進信息的確切含義和自動處理,使得網路信息可被整合。RDF語句由資源、屬性和屬性值組成。RDF文檔包括`<rdf:RDF>`根元素和`<r... ...
  • 這段時間來,AI已經逐步走進我們的工作和生活,作為程式員來說,讓AI寫代碼已經成為稀鬆平常的操作了,今天給大家介紹一個更牛逼的操作,屏幕截屏轉化為代碼,從此前端開發更簡單 screenshot-to-code screenshot-to-code可以將任何屏幕截圖或設計轉換為乾凈的代碼,它是一個簡單 ...
  • title: Vuex 4與狀態管理實戰指南 date: 2024/6/6 updated: 2024/6/6 excerpt: 這篇文章介紹了使用Vuex進行Vue應用狀態管理的最佳實踐,包括為何需要狀態管理,Vuex的核心概念如store、actions、mutations和getters,以及 ...
  • ‍ 寫在開頭 點贊 + 收藏 學會 [webpack由淺入深]系列的內容 第一層: 瞭解一個小功能的完整流程. 看完可以滿足好奇心和應付原理級別面試. 第二層: 源碼陪讀, webpack源碼比較靈活, 自己看容易陷入迷惑. 文章里會貼出關鍵流程的代碼來輔助閱讀源碼. 如果你正在 ...
  • 工作中難免會遇到各種各樣的數據結構,較為全面的瞭解數組操作,對於複雜數據結構的處理會非常有用且節省時間。所以想在這裡總結一下工作中常用的數組操作,都是一些非常基礎的知識,大家看個樂就好~ ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...