認識 Promise

認識 Promise

前言:為什么會出現 Promise?

最常見的一個場景就是 ajax 請求,通俗來說,由于網速的不同,可能你得到返回值的時間也是不同的,這個時候我們就需要等待,結果出來了之后才知道怎么樣繼續下去。

在 ajax 的原生實現中,利用了 onreadystatechange 事件,當該事件觸發并且符合一定條件時,才能拿到想要的數據,之后才能開始處理數據,這樣做看上去并沒有什么麻煩,但如果這個時候,我們還需要另外一個 ajax 請求,這個新 ajax 請求的其中一個參數,得從上一個 ajax 請求中獲取,這個時候我們就不得不等待上一個接口請求完成之后,再請求后一個接口

let xhr = new XMLHttpRequest();
xhr.open('get', 'https://...');
xhr.send();
xhr.onreadystatechange = function () {if (xhr.readyState === 4) {if (xhr.status >= 200 && xhr.status < 300) {console.log(xhr.responseText)//偽代碼....let xhr = new XMLHttpRequest();xhr.open('get','http://www.xx.com?a'+xhr.responseText);xhr.send();xhr.onreadystatechange = function(){if(xhr.readyState === 4){if(xhr.status>=200 && xhr.status<300){console.log(xhr.responseText)}}}}}
}

當出現第三個 ajax(甚至更多)仍然依賴上一個請求時,我們的代碼就變成了一場災難。

這場災難,往往也被稱為回調地獄

因此我們需要一個叫做 Promise 的東西,來解決這個問題,當然,除了回調地獄之外,還有個非常重要的需求就是:為了代碼更加具有可讀性和可維護性,我們需要將數據請求與數據處理明確的區分開來

上面的寫法,是完全沒有區分開,當數據變得復雜時,也許我們自己都無法輕松維護自己的代碼了。這也是模塊化過程中,必須要掌握的一個重要技能,請一定重視。

1. Promise 是什么?

Promise 是異步編程的一種解決方案,比傳統的解決方案回調函數更合理、更強大。

ES6 將其寫進了語言標準,統一了用法,原生提供了 Promise 對象。

指定回調函數的方式也變得更加靈活易懂,也解決了異步回調地獄的問題

舊方案是單純使用回調函數,常見的異步操作有:定時器、fs 模塊、ajax、數據庫操作

  • 從語法上說,Promise 是一個構造函數;
  • 從功能上說,Promise 對象用來封裝一個異步操作并可以獲取其成功 / 失敗的結果值。

2. Promise 的優點

  1. 指定回調函數的方式更加靈活

    1. 舊的方法:必須在啟動異步任務前指定

    2. promise:啟動異步任務 -> 返回 promise 對象 -> 給 promise 對象綁定回調函數

      (甚至可以在異步任務結束后指定多個)

  2. 可以解決回調地獄問題,支持鏈式調用

    1. 什么是回調地獄?

      回調函數嵌套調用,外部回調函數異步執行的結果是嵌套的回調執行的條件

    2. 回調地獄的缺點?

      不便于閱讀、不便于異常處理

    3. 解決方案?

      promise鏈式調用

    4. 終極解決方案

      async / await

3. 定義 Promise 對象

new Promise((resolve, reject) => { ... });

3.1 Promise 實例對象的兩個屬性

  1. PromiseState

    此屬性為 promise 對象的狀態屬性。

    • fulfilled:成功的狀態
    • rejected:失敗的狀態
    • pending:初始化的狀態

    【注】狀態只能由 pending -> fulfilled 或是 pending -> rejected

  2. PromiseResult

    此屬性為 promise 對象的結果值(resolve 以及 reject 函數的形參值)

3.2 Promise 實例對象的兩個參數

  1. resolve

    修改 promise 對象的狀態,由 pending 修改為 fulfilled;

    將實參設置到這個屬性 PromiseResult 中。

  2. reject

    修改 promise 對象的狀態,由 pending 修改為 rejected;

    將實參設置到這個屬性 PromiseResult 中。

let p = new Promise((resolve, reject) => {// 調整狀態// reject(new Error("error")); // 狀態為 rejectedresolve("success"); // 狀態為 resolved
});
console.log(p); // Promise { <pending> }

4. Promise 對象的狀態

Promise 對象通過自身的狀態來控制異步操作,Promise 實例具有三種狀態.

  1. 異步操作未完成:pending
  2. 異步操作成功:fulfilled
  3. 異步操作失敗:rejected

這三種的狀態的變化途徑只有兩種

  • 從 pending(未完成)到 fulfilled(成功)
  • 從 pending(未成功)到 rejected(失敗)

一旦狀態發生變化,就凝固了,不會再有新的狀態變化,這也是 Promise 這個名字的由來,它的英語意思 “承諾”,一旦承諾生效,就不得再改變了,這也意味著 Promise 實例的狀態變化只可能發生一次

在 Promise 對象的構造函數中,將一個函數作為第一個參數。而這個函數,就是用來處理 Promise 的狀態變化。

上面的 resolve 和 reject 都為一個函數,他們的作用分別是將狀態修改為 resolved 或 rejected。

因此,Promise 的最終結果只有兩種情況:

  1. 異步操作成功,Promise 實例傳回一個值(value),狀態變為 fulfilled;
  2. 異步操作失敗,Promise 實例拋出一個錯誤(error),狀態變為 rejected

5. then 方法(重要)

實例化 Promise 時,使用回調函數作為參數,回調函數通常有兩個參數:

  1. resolve 參數

    當執行到 resolve( ... ) 時,會調用 then 方法中的第一個參數(回調);

  2. reject 參數

    當執行到 reject( ... ) 時,會調用 then 方法中的第二個參數(回調);

then 方法中通常有兩個回調函數作為參數,第一個回調在成功時(resolve)調用,第二個回調在出錯時(reject)調用,第二個參數可以省略。

5.1 then 方法返回結果

調用 then 方法的返回結果是 Promise 對象,對象狀態由回調函數的執行結果決定

  1. 返回結果是非 Promise 類型的屬性

    返回狀態 resolved(成功),返回值為對象成功的值

    const result = p.then((data) => {console.log(data);return 123;},(error) => { console.warn(error); }
    );console.log(result); // 返回值為 123
    

    如果未使用 return 進行返回,則返回值為 undefined。

  2. 返回 Promise 對象

    返回值和返回狀態均由返回的 promise 對象的返回值和狀態決定

    const result = p.then((data) => {console.log(data);return new Promise((resolve, reject) => {resolve("ok");// reject("出錯了");});},(error) => { console.warn(error); }
    );
    console.log(result); // 返回狀態為 resolved,返回值為 ok
    // console.log(result); // 返回狀態為 rejected,返回值為 出錯了
    
  3. 拋出錯誤

    返回狀態 rejected(失敗)

    const result = p.then((data) => {console.log(data);// throw new Error("出錯了");throw "出錯了";},(error) => { console.warn(error); }
    );console.log(result); // 返回狀態為 rejected,返回值為 出錯了
    

5.2 then 方法的鏈式調用

由于 promise 可以返回 promise 對象,因此可以進行鏈式調用

// 鏈式調用
p.then((data) => {},(error) => {}
).then((data) => {},// 失敗回調可以省略
)...;

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/76516.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/76516.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/76516.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

純c++實現transformer 訓練+推理

項目地址 https://github.com/freelw/cpp-transformer C 實現的 Transformer 這是一個無需依賴特殊庫的 Transformer 的 C 實現&#xff0c;涵蓋了訓練與推理功能。 本項目使用C復刻了《Dive into Deep Learning》中關于 Transformer 的第 11 章11.7小節點內容。構建了一個英…

Go 語言規范學習(7)

文章目錄 Built-in functionsAppending to and copying slicesClearCloseManipulating complex numbersDeletion of map elementsLength and capacityMaking slices, maps and channelsMin and maxAllocationHandling panicsBootstrapping PackagesSource file organizationPac…

Python Cookbook-5.1 對字典排序

任務 你想對字典排序。這可能意味著需要先根據字典的鍵排序&#xff0c;然后再讓對應值也處于同樣的順序。 解決方案 最簡單的方法可以通過這樣的描述來概括:先將鍵排序&#xff0c;然后由此選出對應值: def sortedDictValues(adict):keys adict.keys()keys.sort()return …

Git Rebase 操作中丟失提交的恢復方法

背景介紹 在團隊協作中,使用 Git 進行版本控制是常見實踐。然而,有時在執行 git rebase 或者其他操作后,我們可能會發現自己的提交記錄"消失"了,這往往讓開發者感到恐慌。本文將介紹幾種在 rebase 后恢復丟失提交的方法。 問題描述 當我們執行以下操作時,可能…

C語言基礎要素(019):輸出ASCII碼表

計算機以二進制處理信息&#xff0c;但二進制對人類并不友好。比如說我們規定用二進制值 01000001 表示字母’A’&#xff0c;顯然通過鍵盤輸入或屏幕閱讀此數據而理解它為字母A&#xff0c;是比較困難的。為了有效的使用信息&#xff0c;先驅者們創建了一種稱為ASCII碼的交換代…

鴻蒙定位開發服務

引言 鴻蒙操作系統&#xff08;HarmonyOS&#xff09;作為面向萬物互聯時代的分布式操作系統&#xff0c;其定位服務&#xff08;Location Kit&#xff09;為開發者提供了多場景、高精度的位置能力支持。本文將從技術原理、開發流程到實戰案例&#xff0c;全面解析鴻蒙定位服務…

rknn_convert的使用方法

rknn_convert是RKNN-Toolkit2提供的一套常用模型轉換工具&#xff0c;通過封裝上述API接口&#xff0c;用戶只需編輯模型對應的yml配置文件&#xff0c;就可以通過指令轉換模型。以下是如何使用rknn_convert工具的示例命令以及支持的指令參數&#xff1a; python -m rknn.api.…

解決 axios get請求瞎轉義問題

在Vue.js項目中&#xff0c;axios 是一個常用的HTTP客戶端庫&#xff0c;用于發送HTTP請求。qs 是一個用于處理查詢字符串的庫&#xff0c;通常與 axios 結合使用&#xff0c;特別是在處理POST請求時&#xff0c;將對象序列化為URL編碼的字符串。 1. 安裝 axios 和 qs 首先&a…

【XTerminal】【樹莓派】Linux系統下的函數調用編程

目錄 一、XTerminal下的Linux系統調用編程 1.1理解進程和線程的概念并在Linux系統下完成相應操作 (1) 進程 (2)線程 (3) 進程 vs 線程 (4)Linux 下的實踐操作 1.2Linux的“虛擬內存管理”和stm32正式物理內存&#xff08;內存映射&#xff09;的區別 (1)Linux虛擬內存管…

torch 拆分子張量 分割張量

目錄 unbind拆分子張量 1. 沿著第n個維度拆分&#xff08;即按“批次”拆分&#xff09; split分割張量 常用用法&#xff1a; 總結&#xff1a; unbind拆分子張量 import torchquaternions torch.tensor([[1, 2, 3, 4], [5, 6, 7, 8]]) result torch.unbind(quaternio…

【Linux】內核驅動學習筆記(二)

7、framebuffer驅動詳解 7.1、什么是framebuffer (1)裸機中如何操作LCD (2)OS下操作LCD的難點 (3)framebuffer幀緩沖&#xff08;簡稱fb&#xff09;是linux內核中虛擬出的一個設備 (4)framebuffer向應用層提供一個統一標準接口的顯示設備 (5)從驅動來看&#xff0c;fb是一個…

用 Docker Compose 與 Nginx 反向代理部署 Vikunja 待辦事項管理系統

在高效管理日常任務和項目的過程中&#xff0c;開源待辦事項工具 Vikunja 以其簡潔、直觀的設計和多視圖支持受到越來越多用戶的青睞。本文將詳細介紹如何使用 Docker Compose 快速部署 Vikunja&#xff0c;并通過 Nginx 反向代理實現 HTTPS 訪問&#xff0c;從而確保服務安全穩…

使用Python快速接入DeepSeek API的步驟指南

使用Python快速接入DeepSeek API的步驟指南 1. 前期準備 注冊DeepSeek賬號 訪問DeepSeek官網注冊賬號 完成郵箱驗證等認證流程 獲取API密鑰 登錄后進入控制臺 → API管理 創建新的API Key并妥善保存 安裝必要庫 pip install requests # 可選&#xff1a;處理復雜場景 pip…

Redis 主要能夠用來做什么

Redis&#xff08;Remote Dictionary Server&#xff09;是一種基于內存的鍵值存儲數據庫&#xff0c;它的性能極高&#xff0c;廣泛應用于各種高并發場景。以下是 Redis 常見的用途&#xff1a; 1. 緩存&#xff08;Cache&#xff09; 作用&#xff1a;存儲熱點數據&#xf…

印度股票實時數據API接口選型指南:iTick.org如何成為開發者優選

在全球金融數字化浪潮中&#xff0c;印度股票市場因其高速增長潛力備受關注。對于量化交易開發者、金融科技公司而言&#xff0c;穩定可靠的股票報價API接口是獲取市場數據的核心基礎設施。本文將深度對比主流印度股票API&#xff0c;并揭示iTick在數據服務領域的獨特優勢。 一…

24.多路轉接-poll

poll也是一種linux中的多路轉接的方案 解決select的fd有上限的問題解決select每次調用都要重新設置關心的fd poll函數接口 poll, ppoll - wait for some event on a file descriptor#include <poll.h>int poll(struct pollfd *fds, nfds_t nfds, int timeout);DESCRIP…

Linux 基礎入門操作 前言 linux操作指令介紹

1 linux 目錄介紹 Linux 文件系統采用層次化的目錄結構&#xff0c;所有目錄都從根目錄 / 開始 1.1 核心目錄 / (根目錄) 整個文件系統的起點、包含所有其他目錄和文件 /bin (基本命令二進制文件) 存放系統最基本的shell命令&#xff1a;如 ls, cp, mv, rm, cat 等&#…

Chrome開發者工具實戰:調試三劍客

在前端開發的世界里&#xff0c;Chrome開發者工具就是我們的瑞士軍刀&#xff0c;它集成了各種強大的功能&#xff0c;幫助我們快速定位和解決代碼中的問題。今天&#xff0c;就讓我們一起來看看如何使用Chrome開發者工具中的“調試三劍客”&#xff1a;斷點調試、調用棧跟蹤和…

函數柯里化(Currying)介紹(一種將接受多個參數的函數轉換為一系列接受單一參數的函數的技術)

文章目錄 柯里化的特點示例普通函數柯里化實現使用Lodash進行柯里化 應用場景總結 函數柯里化&#xff08;Currying&#xff09;是一種將接受多個參數的函數轉換為一系列接受單一參數的函數的技術。換句話說&#xff0c;柯里化將一個多參數函數轉化為一系列嵌套的單參數函數。 …

torch.nn中的非線性激活介紹合集——Pytorch中的非線性激活

1、nn.ELU 基本語法&#xff1a; class torch.nn.ELU(alpha1.0, inplaceFalse)按元素應用 Exponential Linear Unit &#xff08;ELU&#xff09; 函數。 論文中描述的方法&#xff1a;通過指數線性單元 &#xff08;ELU&#xff09; 進行快速準確的深度網絡學習。 ELU 定義為…