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
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...