「每日一題」面試官問你對Promise的理解?多是須要你能手動實現各個特性

關注公衆號「鬆寶寫代碼」,精選好文,每日一題面試

加入咱們一塊兒學習,day day up算法

做者:saucxs | songEagle

來源:原創promise

1、前言

2020.12.23日剛立的flag,每日一題,題目類型不限制,能夠是:算法題,面試題,闡述題等等。框架

每日一題

往期「每日一題」:異步

接下來是第3道:談談你對 promise 的理解?函數

2、談談你對 promise 的理解?

一、咱們簡單歸納一下promise

Promise 是 ES6 新增的語法,解決了回調地獄的問題。學習

不管是ES6的Promise也好,jQuery的Promise也好,不一樣的庫有不一樣的實現,可是你們遵循的都是同一套規範,因此,Promise並不指特定的某個實現,它是一種規範,是一套處理JavaScript異步的機制。this

Promise 本質上就是一個綁定了回調的對象,而不是將回調傳回函數內部。spa

因此,Promise在必定程度上解決了回調函數的書寫結構問題,但回調函數依然在主流程上存在,只不過都放到了then(...)裏面,和咱們大腦順序線性的思惟邏輯仍是有出入的。code

二、咱們說一下promise相關規範

  • 能夠把 Promise 當作一個狀態機。初始是 pending 狀態,能夠經過函數 resolve 和 reject ,將狀態轉變爲 resolved 或者 rejected 狀態,狀態一旦改變就不能再次變化。
  • then 函數會返回一個 Promise 實例,而且該返回值是一個新的實例而不是以前的實例。由於 Promise 規範規定除了 pending 狀態,其餘狀態是不能夠改變的,若是返回的是一個相同實例的話,多個 then 調用就失去意義了。
  • then 方法能夠被同一個 promise 調用屢次。
  • 值穿透

3、promise 是如何實現的?

一、Promise的簡單使用

Promise的簡單使用

咱們經過這種使用構建Promise實現的最第一版本

二、Promise的大體框架

大體框架有了,可是Promise狀態,resolve函數,reject函數,以及then等回調沒有詳細處理

Promise的大體框架

三、Promise的鏈式存儲

咱們先看一個例子:

Promise的鏈式存儲

每間隔1秒打印一個數字,哈哈,這個不是真實的間隔1秒,汪汪,

這個的輸出是啥?

打印順序:一、二、3

這裏咱們能確認的是:

  • 讓a,b,c的只能在then的回調接收到
  • 在連續的異步調用中,如何保證異步函數的執行順序

Promise一個常見的需求就是連續執行兩個或者多個異步操做,這種狀況下,每個後來的操做都在前面的操做執行成功以後,帶着上一步操做所返回的結果開始執行。這裏用setTimeout來處理.

Promise的鏈式存儲

四、Promise的狀態機制和執行順序

爲了保證Promise的異步操做時的順序執行,這裏給Promise加上狀態機制

Promise的狀態機制和執行順序

五、Promise的遞歸執行

每一個Promise後面連接一個對象,該對象包含onresolved,onrejected,子promise三個屬性.

當父Promise 狀態改變完畢,執行完相應的onresolved/onrejected的時候,拿到子promise,在等待這個子promise狀態改變,在執行相應的onresolved/onrejected。依次循環直到當前promise沒有子promise。

Promise的遞歸執行

六、Promise的異常處理

每一個Promise後面連接一個對象,該對象包含onresolved,onrejected,子promise三個屬性.

當父Promise 狀態改變完畢,執行完相應的onresolved/onrejected的時候,拿到子promise,在等待這個子promise狀態改變,在執行相應的onresolved/onrejected。依次循環直到當前promise沒有子promise。

Promise的異常處理

七、Promise的then的實現

then 方法是 Promise 的核心,這裏作一下詳細介紹。

promise.then(onFulfilled, onRejected)

一個 Promise 的then接受兩個參數: onFulfilled和onRejected(都是可選參數,而且爲函數,若不是函數將被忽略)

  • onFulfilled 特性:

當 Promise 執行結束後其必須被調用,其第一個參數爲 promise 的終值,也就是 resolve 傳過來的值
在 Promise 執行結束前不可被調用
其調用次數不可超過一次

  • onRejected 特性

當 Promise 被拒絕執行後其必須被調用,第一個參數爲 Promise 的拒絕緣由,也就是reject傳過來的值
在 Promise 執行結束前不可被調用
其調用次數不可超過一次

  • 調用時機

onFulfilled 和 onRejected 只有在執行環境堆棧僅包含平臺代碼時纔可被調用(平臺代碼指引擎、環境以及 promise 的實施代碼)

  • 調用要求

onFulfilled 和 onRejected 必須被做爲函數調用(即沒有 this 值,在 嚴格模式(strict) 中,函數 this 的值爲 undefined ;在非嚴格模式中其爲全局對象。)

  • 屢次調用

then 方法能夠被同一個 promise 調用屢次

當 promise 成功執行時,全部 onFulfilled 需按照其註冊順序依次回調
當 promise 被拒絕執行時,全部的 onRejected 需按照其註冊順序依次回調

  • 返回

then方法會返回一個Promise,關於這一點,Promise/A+標準並無要求返回的這個Promise是一個新的對象,但在Promise/A標準中,明確規定了then要返回一個新的對象,目前的Promise實現中then幾乎都是返回一個新的Promise(詳情)對象,因此在咱們的實現中,也讓then返回一個新的Promise對象。

promise2 = promise1.then(onFulfilled, onRejected);
  • 若是 onFulfilled 或者 onRejected 返回一個值 x ,則運行下面的 Promise 解決過程:[[Resolve]](promise2, x)
  • 若是 onFulfilled 或者 onRejected 拋出一個異常 e ,則 promise2 必須拒絕執行,並返回拒因 e
  • 若是 onFulfilled 不是函數且 promise1 成功執行, promise2 必須成功執行並返回相同的值
  • 若是 onRejected 不是函數且 promise1 拒絕執行, promise2 必須拒絕執行並返回相同的拒因

不論 promise1 被 reject 仍是被 resolve , promise2 都會被 resolve,只有出現異常時纔會被 rejected。

每一個Promise對象均可以在其上屢次調用then方法,而每次調用then返回的Promise的狀態取決於那一次調用then時傳入參數的返回值,因此then不能返回this,由於then每次返回的Promise的結果都有可能不一樣。

Promise的then的實現

八、Promise的值穿透

Promise的then的實現

咱們來看一下這個題的輸出:

Promise的then的實現

最終打結果是1而不是2.

咱們再來看一下這個題的輸出:

Promise的then的實現

各類福利

鬆寶寫代碼

「鬆寶寫代碼」公衆號:開發知識體系構建,技術分享,項目實戰,實驗室,每日一題,帶你一塊兒學習新技術,總結學習過程,讓你進階到高級資深工程師,學習項目管理,思考職業發展,生活感悟,充實中成長起來。問題或建議,請公衆號留言。

一、字節內推福利

回覆「校招」獲取內推碼

回覆「社招」獲取內推

回覆「實習生」獲取內推

後續會有更多福利

二、學習資料福利

回覆「算法」獲取算法學習資料

三、每日一題

The End

若是你以爲這篇文章對你有幫助,有啓發,可能幫助到更多的人,我想請你幫我幾個小忙:

一、點個「在看」,讓更多的人也能看到這篇文章內容。

二、點個「贊」,是對文章的確定。

三、點個「分享」到朋友圈,是爲了讓更多的人知道你在學習提高本身。

四、關注「鬆寶寫代碼」,後臺回覆「加羣」 加入咱們一塊兒學習。

相關文章
相關標籤/搜索