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