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