Promise 到底是什么?看這個小故事

大家好,我是若川,點此加我微信進源碼群,一起學習源碼。

還可以進《劍指前端offer》交流群。

另外,可以進群免費看下周六Vue專場直播,有尤雨溪分享「Vue3 生態現狀以及展望

如果你還是一個 JavaScript 初學者,你可能要糾結一下 Promise 到底是什么。

最近我發了一條動態,描述了這個問題,我被大家的反饋震驚到了。所以我決定寫一篇關于 Promise 的教程。

我看過很多關于 Promise 的文章,但大部分教程都沒有通過類比的方式解釋清楚 Promise 到底是什么。初學者搞不懂 Promise 的根本原因是他們不知道 Promise 是做什么的,以及如何在簡單和復雜的場景中使用它。

因此在這篇教程中,我將通過一個小故事來解釋什么是 Promise、Promise 是如何工作的。同時我也會通過一些代碼示例來說明在 JavaScript 中如何使用 Promise。

什么是 Promise

想象一下,你準備面試某個公司的前端工程師。

你走進面試會場,當面試馬上要開始時你發現簡歷忘帶了,這時你怎么辦?

你沒有氣餒。因為你很幸運,你有一個室友。

你馬上給室友打電話尋求幫助,懇求室友幫你找到簡歷。你的室友承諾他一旦找到就立馬回你消息。

假設簡歷被找到,室友給你回復信息:

“太好了,我找到你的簡歷了!”

但是如果室友沒有找到,他就要回復一條失敗的信息,并解釋他為什么沒有找到簡歷。比如,他可能給正在面試的你發如下信息:

“對不起,我沒有找到你的簡歷,因為你的保險柜鑰匙丟了。”

與此同時,面試還要繼續。但面試官并沒有拿到真實的簡歷,而是得到一個正在找簡歷的承諾,同時面試官把該簡歷的狀態設置成進行中(PENDING)

你回答了所有問題。但不幸的是,能否得到這個工作還要依賴你簡歷的最終狀態(FINAL STATUS)

你的室友終于回消息了。正如我們前面討論過的,如果他沒有找到簡歷,他就需要發一個失敗的信息并解釋為什么沒有找到。

如果是這種情況,面試結束,你被拒絕(Rejected)了。

如果室友找到了簡歷,他會很高興的告訴你他找到了,而你將繼續面試,并獲得(FULFILL)這份工作。

如何把上述過程翻譯成 JS 代碼

室友承諾找簡歷并回復信息的過程等同于我們在 JavaScript 中定義一個 Promise。定義 Promise 并不能直接或立即獲得返回值,而是返回一個 Promise 對象。這個 Promise 對象在一段時間后會接收返回值。

Promise 對象是異步的,這就意味著程序需要花點時間才能獲得結果。這和找簡歷是一樣的,都需要花點時間去找。

基于這個原因,在找的這個時間里,面試官并不是什么都沒做,而是基于簡歷一會兒就找到的承諾,他們依然開始面試候選人。在這個場景里,我們用簡歷一會兒就找到的承諾替換了真實的簡歷

同理,JS 引擎也并不是等著什么也不做,而是繼續執行后續代碼,并將返回的Promise對象狀態設置為 Pending

回復信息包含是否找到簡歷的狀態信息。對于Promise對象來說,回復信息被稱作返回值。

如果回復信息是 “success”,我們將錄取候選人。如果是 “failure”,我們不錄取該候選人。

在 Promise 中,我們通過回調函數處理Promise的返回值。這些處理函數定義在then()方法中。

為了指定如何調用回調函數,需要使用以下兩個方法:

  • resolve(value): 表明 Promise 任務成功,調用then()的成功回調函數。

  • reject(error): 表明 Promise 任務失敗,調用then()的錯誤回調函數。

如果 Promise 成功,則調用成功回調,如果失敗,調用失敗回調。

在異步任務完成之前,Promise 只是一個占位符。當你定義了一個 Promise,你并不會立即獲得返回值,而是獲得一個 Promise 對象。

如何在 JavaScript 中使用 Promise

你可以通過Promise類定義一個 Promise 對象。

const?myPromise?=?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{resolve('this?is?the?eventual?value?the?promise?will?return');},?3000);
});console.log(myPromise);

示例 1

在控制臺運行將返回一個Promise對象:

bbdd304bcef49a181fe66e0371f81b16.png

除了通過構造函數聲明一個 Promise 對象外,還可以使用 Promise 內置的 API 進行聲明:

const?anotherPromise?=?Promise.resolve("this?is?the?eventual?value?the?promise?will?return")console.log(anotherPromise);

示例 2

示例 1 中的 Promise 等待 3s 后獲取到成功返回的信息:this is the eventual...,而示例 2 中將立即獲取到成功返回的信息。

JavaScript Promise 中的錯誤處理

Promise 對象也能被_rejected_。大多數時候,rejected ?的發生是因為執行異步任務的時候拋出了錯誤,此時就會調用reject()方法。

下面的示例展示了一個 Promise 對象是如何執行 reject 方法的:

const?myPromise?=?new?Promise((resolve,?reject)?=>?{let?a?=?false;setTimeout(()?=>?{return?(a)???resolve('a?is?found!'):?reject('sorry,?no?a');},?3000);
});

示例 3

你能想到 Promise 被 rejected 的原因嗎?如果你的答案是:a的值是 false,那么恭喜你答對了。

在示例 3 中,代碼執行 3s 后將調用 reject 方法,因為(a)?表達式的值是 false,所以觸發reject方法。

Promise 的鏈式調用

當 Promise 返回了某個值,通常你都會對返回值進行處理。

比如,你發送了一個網絡請求,你期望獲取數據并展示在頁面上。

你可以定義兩個回調函數,當 Promise 返回成功或失敗時進行回調。這兩個回調函數定義在then()內:

const?anotherPromise?=?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{resolve('this?is?the?eventual?value?the?promise?will?return');},?3000);
});//?CONTINUATION
anotherPromise
.then(value?=>?{?console.log(value)?})

示例 4

示例 4 的代碼在 3s 后返回成功信息:

5005e8878f6f4801f97121d00902458f.png

原則上你可以無限鏈式調用,調用鏈會依次執行,而且前一個 then 的返回值作為參數傳入后一個 then。

const?anotherPromise?=?new?Promise((resolve,?reject)?=>?{setTimeout(()?=>?{resolve('this?is?the?eventual?value?the?promise?will?return');},?3000);
});anotherPromise
.then(fulfillFn,?rejectFn)
.then(fulfilFn,?rejectFn)
.then(value?=>?{?console.log(value)?})

示例 5

但我們還是遺漏了重要的內容。

要時刻記住,then()方法必須有兩個回調函數:第一個參數是成功回調,第二個參數是錯誤回調。

在示例 4 和示例 5 中都沒有傳入第二個回調函數。因此,如果代碼報錯,就沒有錯誤回調捕獲錯誤信息。

如果你執意要在then()中只定義一個回調函數(即成功回調),那么你就需要在 Promise 調用鏈的末端調用catch()方法捕獲任何可能的報錯信息。

如何在 JS 中使用catch()方法

在 Promise 調用鏈上,無論哪個環節報錯,catch()方法都會被調用。

const?myPromise?=?new?Promise((resolve,?reject)?=>?{let?a?=?false;setTimeout(()?=>?{return?(a)???resolve('a?is?found!'):?reject('sorry,?no?a');},?3000);
});?myPromise
.then(value?=>?{?console.log(value)?})
.catch(err?=>?{?console.log(err)?});

示例 6

因為myPromise最終狀態是 rejected,then()方法中的成功回調被忽略。而catch()方法中的錯誤回調被執行,并在控制臺打印如下錯誤信息:

773facf671bc14547c14141b832b7f30.png

寫在最后

JavaScript 中的 Promise 是一個運行異步任務的強大功能。大部分情況下,在前端面試時,面試官都會問一些關于 Promise 的問題。

在這片文章中,我已經解釋了 Promise 的簡單應用場景,也通過示例的方式展示了基本用法。

希望你能從文章中獲取有用的知識。如果你喜歡編程教程,點擊查看我的博客。我會經常發布一些有關軟件開發的文章。

再次感謝您的閱讀,再會。

P/S: ?如果你也在學習 JavaScript,我也創建了一個電子書,上面有 50 個關于 js 的主題,而且都是我親自手繪的哦。


原文鏈接:https://www.freecodecamp.org/news/what-is-promise-in-javascript-for-beginners/

作者:Kingsley Ubah

譯者:wangzili


最后預告福利:掃下方二維碼加我微信 ruochuan12,可以拉你進群免費觀看10月23日的前端早早聊?Vue 專場直播,大咖云集?,更有「尤雨溪」分享「Vue3 生態現狀以及展望」。?另外還可以送50個錄播視頻和PPT~

3213bf819f0a5e2bb406590a68ebf4ed.png

最近組建了一個湖南人的前端交流群,如果你是湖南人可以加我微信?ruochuan12?私信 湖南?拉你進群。


推薦閱讀

1個月,200+人,一起讀了4周源碼
我歷時3年才寫了10余篇源碼文章,但收獲了100w+閱讀

老姚淺談:怎么學JavaScript?

我在阿里招前端,該怎么幫你(可進面試群)

8f46b290b066cb3eaa7762ef6c5fc7b7.gif

·················?若川簡介?·················

你好,我是若川,畢業于江西高校。現在是一名前端開發“工程師”。寫有《學習源碼整體架構系列
從2014年起,每年都會寫一篇年度總結,已經寫了7篇,點擊查看年度總結。
同時,最近組織了源碼共讀活動

a885e1c6dbb7e96c45659ecc72f0ad94.png

識別方二維碼加我微信、拉你進源碼共讀

今日話題

略。歡迎分享、收藏、點贊、在看我的公眾號文章~

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

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

相關文章

docker 修改服務器,docker-修改容器掛載目錄的3種方法小結

本文關鍵詳細介紹了docker-修改容器初始化目錄的3種方式總結,具備非常好的實用價值,期待對大伙兒有一定的協助。一起追隨我回來瞧瞧吧方法一:修改配置文件(需停止docker服務)1、停止docker服務systemctl stop docker.service(重要&#xff0c…

什么是測試開發

aaa轉載于:https://www.cnblogs.com/Chamberlain/p/10730856.html

DropDownList 控件不能觸發SelectedIndexChanged 事件的另一個原因

相信DropDownList 控件不能觸發SelectedIndexChanged 事件已經不是什么新鮮事情了,原因也無外乎以下幾種: 1、DropDownList 控件的屬性 AutoPostBack"True" 沒有寫; 2、DropDownList 控件的數據綁定沒有放在if (!Page.IsPostBack) …

Vue 團隊公開快如閃電的全新腳手架工具,未來將替代 Vue-CLI,才300余行代碼,學它!...

1. 前言大家好,我是若川。歡迎關注我的公眾號若川視野源碼共讀活動ruochuan12想學源碼,極力推薦之前我寫的《學習源碼整體架構系列》jQuery、underscore、lodash、vuex、sentry、axios、redux、koa、vue-devtools、vuex4、koa-compose、vue-next-release…

斑馬無線打印服務器,如何設置斑馬打印機無線WiFi

安裝Zebra Setup Utilities.exe,打開軟件(沒有該軟件的可以向客服索要)界面如果是英文請選擇options(選項),選擇應用程序語言Simplified Chinese(簡體中文)點擊確定,關閉軟件,重新打開,界面就會顯示中文。點擊相應的打…

Python自然語言處理學習筆記(19):3.3 使用Unicode進行文字處理

3.3 Text Processing with Unicode 使用Unicode進行文字處理 Our programs will often need to deal with different languages, and different character sets. The concept of “plain text” is a fiction(虛構). If you live in the English-speakin…

小程序卡片疊層切換卡片_現在,卡片和清單在哪里?

小程序卡片疊層切換卡片重點 (Top highlight)介紹 (Intro) I was recently tasked to redesign the results of the following filters:我最近受命重新設計以下過濾器的結果: Filtered results for users (creatives) 用戶的篩選結果(創意) 2. Filtered results fo…

記一次Sentry部署過程

前言 Sentry 是一個開源的實時錯誤報告工具,支持前后端、其他后端語言以及主流框架等。既然是開源,那么我們可以在自己的服務器上搭建,本文記錄搭建的過程以及搭建過程中遇到的一些問題,也可以跟著這個教程來搭建一遍 部署環境 Ub…

效率神器!UI 稿智能轉換成前端代碼

做前端,不搬磚大家好,我是若川。從事前端五年之久,也算見證了前端數次變革,從到DW(Dreamweaver)到H5C3、從JQuery到MVC框架,無數前端大佬在為打造前端完整生態做出努力,由于他們的努…

$.when.apply_When2Meet vs.LettuceMeet:UI和美學方面的案例研究

$.when.apply并非所有計劃應用程序都是一樣創建的。 (Not all scheduling apps are created equal.) As any college student will tell you, we use When2Meet almost religiously. Between classes, extracurriculars, work, and simply living, When2Meet is the scheduling…

BZOJ4825: [Hnoi2017]單旋(Splay)

題面 傳送門 題解 調了好幾個小時……指針太難寫了…… 因為只單旋最值,我們以單旋\(\min\)為例,那么\(\min\)是沒有左子樹的,而它旋到根之后,它的深度變為\(1\),它的右子樹里所有節點深度不變,其它所有節點…

前端不容你褻瀆

大家好,我是若川,點此加我微信進源碼群,一起學習源碼。同時可以進群免費看Vue專場直播,有尤雨溪分享「Vue3 生態現狀以及展望」背景最近我在公眾號的后臺收到一條留言:言語里充滿了對前端的不屑和鄙夷,但仔…

用jquery阻止事件起泡

jquery使用過程中阻止事件起泡實例 1、通過返回false來取消默認的行為并阻止事件起泡。jQuery 代碼:$("form").bind("submit", function() { return false; })2、通過使用 preventDefault() 方法只取消默認的行為。jQuery 代碼:$("form").bind(…

利益相關者軟件工程_如何向利益相關者解釋用戶體驗的重要性

利益相關者軟件工程With the ever increasing popularity of user experience (UX) design there is a growing need for good designers. However, there’s a problem for designers here as well. How can you show the importance of UX to your stakeholders and convince…

云棲大會上,阿里巴巴重磅發布前端知識圖譜!

大家好,我是若川,點此加我微信進源碼群,一起學習源碼。同時可以進群免費看Vue專場直播,有尤雨溪分享「Vue3 生態現狀以及展望」阿里巴巴前端知識圖譜,由大阿里眾多前端技術專家團歷經1年時間精心整理,從 初…

Linux下“/”和“~”的區別

在linux中,”/“代表根目錄,”~“是代表目錄。Linux存儲是以掛載的方式,相當于是樹狀的,源頭就是”/“,也就是根目錄。 而每個用戶都有”家“目錄,也就是用戶的個人目錄,比如root用戶的”家“目…

在當今移動互聯網時代_誰在提供當今最好的電子郵件體驗?

在當今移動互聯網時代Hey, a new email service from the makers of Basecamp was recently launched. The Verge calls it a “genuinely original take on messaging”, and it indeed features some refreshing ideas for the sometimes painful exercise we call inbox man…

插件式開發小記

在做插件開發時,小記一下,用來備忘: 1.DEV8.2的XtraTabControl控件如何獲得當前打開的子窗體:XtraForm frm (XtraForm)xtraTabControl1.SelectedTabPage.Controls[0];2.插件開發的底層標準最好是抽象類,這樣擴展性好。…

linux運維工程師學習路線

一、學習路線: 1.青銅: 1、Linux基礎知識、基本命令(起源、組成、常用命令如cp、ls、file、mkdir等常見操作命令) 2、Linux用戶及權限基礎 3、Linux系統進程管理進階 4、linux高效文本、文件處理命令(vim、grep、sed、…

React 全新文檔上線!

大家好,我是若川,點此加我微信進源碼群,一起學習源碼。同時可以進群免費看明天的Vue專場直播,有尤雨溪分享「Vue3 生態現狀以及展望」,還可以領取50場錄播視頻和PPT。React 官方文檔改版耗時 1 年,今天已完…