摘要:原理分析一對象用于異步計算。它有兩個參數,分別為在成功和失敗情況下的回調函數。實現根據當前狀態對回調函數進行處理,同時返回一個新的對象,以便鏈式調用。,注冊回調函數到當前的對象中或,立即執行回調函數說明方法只處理被拒絕的情況,并返回一個。
Promise原理分析一
Promise對象用于異步計算。一個Promise對象代表著一個還未完成,但預期將來會完成的操作。
Note:
Promise原理分析二
Promise對象有以下幾種狀態:
pending: 初始狀態, 既不是 fulfilled 也不是 rejected.
fulfilled: 成功的操作.
rejected: 失敗的操作.
pending狀態的Promise對象既可轉換為帶著一個成功值的fulfilled狀態,也可變為帶著一個失敗信息的 rejected狀態。當狀態發生轉換時,Promise.then綁定的方法就會被調用。(當綁定方法時,如果 Promise對象已經處于fulfilled或rejected狀態,那么相應的方法將會被立刻調用,所以在異步操作的完成情況和它的綁定方法之間不存在競爭條件。)
因為Promise.prototype.then和Promise.prototype.catch方法返回Promises對象, 所以它們可以被鏈式調用。
constructor 說明語法
new Promise(executor); new Promise(function(resolve, reject) { ... });
參數
name | desc |
---|---|
executor | 帶有resolve、reject兩個參數的函數對象。第一個參數用在處理執行成功的場景,第二個參數則用在處理執行失敗的場景。一旦我們的操作完成即可調用這些函數。 |
構造函數主要完成狀態的初始化,并提供resolve和reject兩個方法給創建者以轉變狀態。
const utils = require("./utils"); const isFunction = utils.isFunction; const STATUS = { PENDING: "pending", FULFILLED: "fulfilled", REJECTED: "rejected" }; const SYMBOL_STATUS = Symbol("status"); const SYMBOL_DATA = Symbol("data"); const SYMBOL_FULFILLED_CALLBACK = Symbol("fulfilledCallback"); const SYMBOL_REJECTED_CALLBACK = Symbol("rejectedCallback"); class Promise { constructor(executor) { if (!isFunction(executor)) { throw Error(`Promise executor ${executor} is not a function`); } const self = this; // 初始狀態為pending const status = self[SYMBOL_STATUS] = STATUS.PENDING; // 使用symbol實現私有化 self[SYMBOL_FULFILLED_CALLBACK] = undefined; self[SYMBOL_REJECTED_CALLBACK] = undefined; self[SYMBOL_DATA] = undefined; function resovle(value) { // todo } function reject(reason) { // todo } // 執行executor函數,若出現異常則調用reject方法,將狀態變為rejected,同時調用回調函數 try { executor(resovle, reject); } catch (err) { reject(err); } } }
上面代碼中完成了構造函數的雛形,而resolve和reject兩個函數的職責為狀態轉變和回調函數的調用:
resolve,接受一個成功值,傳遞給綁定的fulfilled回調函數中。主要工作是將當前狀態變為fulfilled狀態,同時調用綁定的fulfilled回調函數:
function resovle(value) { const fulfilledCallback = self[SYMBOL_FULFILLED_CALLBACK]; if (status === STATUS.PENDING) { self[SYMBOL_STATUS] = STATUS.FULFILLED; // 狀態轉換 self[SYMBOL_DATA] = value; // 保存成功值 if (isFunction(fulfilledCallback)) { setTimeout(() => { // 不阻塞主流程,在下一個事件輪詢中再調用fulfilled回調函數 fulfilledCallback(value); }); } } }
reject,接受一個失敗信息,傳遞給綁定的rejected回調函數中。主要工作是將當前狀態變為rejected 狀態,同時調用綁定的rejected回調函數:
function reject(reason) { const rejectedCallback = self[SYMBOL_REJECTED_CALLBACK]; if (status === STATUS.PENDING) { self[SYMBOL_STATUS] = STATUS.REJECTED; // 狀態轉換 self[SYMBOL_DATA] = reason; // 保存成功值 if (isFunction(rejectedCallback)) { setTimeout(() => { // 不阻塞主流程,在下一個事件輪詢中再調用rejected回調函數 rejectedCallback(reason); }); } } }
fulfilled`和rejected回調函數是通過Promise.prototype.then和Promise.prototype.catch注冊的。
then 說明then方法返回一個Promise。它有兩個參數,分別為Promise在成功和失敗情況下的回調函數。
語法
p.then(onFulfilled, onRejected); p.then(function(value) { // todo }, function(reason) { // todo });
參數
name | desc |
---|---|
onFulfilled | 一個函數,當Promise的狀態為fulfilled時調用。該函數有一個參數,為成功的返回值。 |
onRejected | 一個函數,當Promise的狀態為rejected時調用。該函數有一個參數,為失敗的原因。 |
根據當前狀態對回調函數進行處理,同時返回一個新的Promise對象,以便鏈式調用。
then(onFulfilled, onRejected) { const self = this; const status = self[SYMBOL_STATUS]; const data = self[SYMBOL_DATA]; const resolveValue = self[SYMBOL_RESOLVE_VALUE]; // 如果onFulfilled不是函數,回調函數僅返回成功值 const fulfilledCallback = isFunction(onFulfilled) ? onFulfilled : function returnFunc(value) { return value; }; // 如果onRejected不是函數,回調函數僅返回失敗信息 const rejectedCallback = isFunction(onRejected) ? onRejected : function throwFunc(reason) { throw reason; }; // 當前狀態為pending if (status === STATUS.PENDING) { // 返回一個新的Promise對象,可以被鏈式調用 return new Promise((resolve, reject) => { // 將fulfilled回調函數注冊到當前Promise對象中(非新Promise對象) self[SYMBOL_FULFILLED_CALLBACK] = value => { // 根據回調函數的執行情況,通過傳遞的新Promise對象的resolve和reject方法對其狀態進行轉變 try { const newValue = fulfilledCallback(value); // 解析成功值 resolveValue(newValue, resolve, reject); } catch (err) { reject(err); } }; // 同上 self[SYMBOL_REJECTED_CALLBACK] = reason => { try { const newReason = rejectedCallback(reason); resolveValue(newReason, resolve, reject); } catch (err) { reject(err); } }; }); } // 當前狀態為fulfilled if (status === STATUS.FULFILLED) { // 返回一個新的Promise對象,可以被鏈式調用 return new Promise((resolve, reject) => { // 在下一個事件輪詢中立即調用fulfilled回調函數,根據執行情況決定新Promise對象的狀態轉變 setTimeout(() => { try { const newValue = fulfilledCallback(data); resolveValue(newValue, resolve, reject); } catch (err) { reject(err); } }); }); } // 當前狀態為rejected if (status === STATUS.REJECTED) { // 返回一個新的Promise對象,可以被鏈式調用 return new Promise((resolve, reject) => { // 在下一個事件輪詢中立即調用rejected回調函數,根據執行情況決定新Promise對象的狀態轉變 setTimeout(() => { try { const newReason = rejectedCallback(data); resolveValue(newReason, resolve, reject); } catch (err) { reject(err); } }); }); } } // 解析傳遞值函數 [SYMBOL_RESOLVE_VALUE](value, resolve, reject) { // 若傳遞值為Promise對象,將新Promise對象的resolve和reject傳遞給Promise傳遞值以觸發狀態的轉換 if (value instanceof Promise) { value.then(resolve, reject); return; } // 若傳遞值不是Promise對象,傳遞給resolve方法 resolve(value); }
根據當前Promise對象的狀態,對回調函數進行注冊或立即執行,同時返回一個新的Promise對象。
pending,注冊回調函數到當前的Promise對象中
fulfilled或rejected,立即執行回調函數
catch 說明catch方法只處理Promise被拒絕的情況,并返回一個Promise。該方法的行為和調用Promise.prototype.then(undefined, onRejected)相同。
語法
p.catch(onRejected); p.catch(function(reason) { // todo });
參數
name | desc |
---|---|
onRejected | 當Promise被拒絕時調用的函數。該函數調用時會傳入一個參數:失敗原因。 |
catch方法是對then方法的包裝,僅傳遞onRejected失敗回調函數。
catch(onRejected) { return this.then(null, onRejected); }總結
現在回顧下Promise的實現過程,其主要使用了設計模式中的觀察者模式:
通過Promise.prototype.then和Promise.prototype.catch方法將觀察者方法注冊到被觀察者Promise對象中,同時返回一個新的Promise對象,以便可以鏈式調用。
被觀察者管理內部pending、fulfilled和rejected的狀態轉變,同時通過構造函數中傳遞的resolve和reject方法以主動觸發狀態轉變和通知觀察者。
關鍵知識點資源 完整代碼Promise
MDN
symbol
ruanyifeng
觀察者模式
百度百科
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/80384.html
摘要:原理分析一說明方法返回一個被拒絕的對象。實現創建一個新的對象,通過其構造函數的參數函數對象將狀態變為。和使用解析值,同時通過構造函數的參數的函數對象觸發的狀態轉變,其中使用數組記錄返回值使用索引值以確保其返回值在結果集中的順序。 Promise原理分析二 前面我們分析了Promise的then和catch方法,接下來我們一起來看看reject、resolve、race和all方法的實現...
摘要:原理剖析第篇之服務端啟動工作原理分析下一大致介紹由于篇幅過長難以發布,所以本章節接著上一節來的,上一章節為原理剖析第篇之服務端啟動工作原理分析上那么本章節就繼續分析的服務端啟動,分析的源碼版本為二三四章節請看上一章節詳見原理剖析第篇之 原理剖析(第 011 篇)Netty之服務端啟動工作原理分析(下) - 一、大致介紹 1、由于篇幅過長難以發布,所以本章節接著上一節來的,上一章節為【原...
摘要:三模式模式其實包含兩部分和。六化在編碼的時候,想要用進行異步操作流程控制,就要將當前的異步回調函數封裝成。 一、什么是promise/deferred 模式 promise/deferred 模式是,根據promise/A 或者它的增強修改版promise/A+ 規范 實現的promise異步操作的一種實現方式。 異步的廣度使用使得回調,嵌套出現,但是一但出現深度的嵌套,就會讓codi...
摘要:異步的發展歷史寫法意為回調函數,即異步操作執行完后觸發執行的函數,例如當請求完成時就會觸發函數。實例生成以后,可以用方法分別指定狀態和狀態的回調函數。第一個回調函數是對象的狀態變為時調用,第二個回調函數是對象的狀態變為時調用。 關于異步 所謂異步,簡單說就是一個任務不是連續完成的,可以理解成該任務被人為分成兩段,先執行第一段,然后轉而執行其他任務,等做好了準備,再回過頭執行第二段。 比...
摘要:鏈式是指在當前達到狀態后,即開始進行下一個后鄰。在中發現沒有指定異步操作失敗的回調時,會直接將函數返回的,后同設為狀態,如此達成執行后續失敗回調的效果。 原文鏈接 前言 前一陣子記錄了promise的一些常規用法,這篇文章再深入一個層次,來分析分析promise的這種規則機制是如何實現的。ps:本文適合已經對promise的用法有所了解的人閱讀,如果對其用法還不是太了解,可以移步我的上...
閱讀 3374·2023-04-26 01:40
閱讀 3080·2021-11-24 09:39
閱讀 1393·2021-10-27 14:19
閱讀 2638·2021-10-12 10:11
閱讀 1298·2021-09-26 09:47
閱讀 1840·2021-09-22 15:21
閱讀 2678·2021-09-06 15:00
閱讀 880·2021-08-10 09:44