Promise 的 revealing-constructor

本文為翻譯:
https://www.i-programmer.info/programming/javascript/11379-javascript-async-promises-the-revealing-constructor-pattern.html

概念解析:
revealing-constructor pattern

揭示性的建構(gòu)模式

Promise 對(duì)構(gòu)造函數(shù)提供私有方法(顯示構(gòu)造函數(shù)模式)的標(biāo)準(zhǔn)方式進(jìn)行了修改。
私有方法是在創(chuàng)建對(duì)象時(shí)作為閉包創(chuàng)建的方法。這是用于創(chuàng)建可從對(duì)象內(nèi)部而不是外部訪問(wèn)的私有變量的標(biāo)準(zhǔn)方法留瞳。唯一的區(qū)別是變量引用了一個(gè)函數(shù)。如:

function myConstructor(){
  var private=0;
  this.myFunction=function(){
      alert(private);
   }
}

這是僅使用一種方法myFunction的對(duì)象的構(gòu)造函數(shù)肾筐。
重要的部分是稱為private的變量慷吊。這不是對(duì)象的一部分馍惹,因?yàn)樗鼪](méi)有聲明為對(duì)象的屬性瑞眼。因此龙宏,如果您嘗試:

var myObject=new myConstructor(); myObject.private=1;

您將看到一個(gè)不存在 private 的錯(cuò)誤。但是伤疙,由于在聲明 myFunction 時(shí)在范圍內(nèi)是private银酗,因此可以將其作為閉包使用:

myObject.myFunction();

確實(shí)顯示private的值。

私有方法使用相同的機(jī)制徒像,所不同的是變量引用了一個(gè)函數(shù)-一個(gè)內(nèi)部函數(shù)黍特,該內(nèi)部函數(shù)不是正在構(gòu)造的對(duì)象的方法。
這是JavaScript Promise用來(lái)解析和拒絕私有方法的機(jī)制锯蛀,但有一些其他的變化灭衷。

私有函數(shù)和變量由傳遞給構(gòu)造函數(shù)的函數(shù)訪問(wèn)。
讓我們看看它是如何工作的旁涤。
假設(shè)您需要將私有變量設(shè)置為某個(gè)值翔曲,但僅在使用構(gòu)造函數(shù)時(shí)才需要。
最簡(jiǎn)單的解決方案是:

function myClass(value){
  var myPrivateVar=value;
  this.myMethod=function(){
      console.log(myPrivateVar);
   }
}

現(xiàn)在拭抬,您可以使用以下方法創(chuàng)建實(shí)例:

var myObject=new myClass(10);
myObject.myMethod();

將打印私有變量的值部默,即10,并且在使用構(gòu)造函數(shù)時(shí)已設(shè)置了該變量造虎,但是該變量現(xiàn)在無(wú)法通過(guò)對(duì)象外部的代碼進(jìn)行更改。
這似乎很簡(jiǎn)單纷闺,但是如果我們進(jìn)一步推動(dòng)這個(gè)想法算凿,就會(huì)變得更加困難。

如果要在構(gòu)造函數(shù)調(diào)用中傳遞與正在構(gòu)造的對(duì)象的私有成員一起使用的函數(shù)犁功,會(huì)發(fā)生什么情況氓轰?該函數(shù)旨在由構(gòu)造函數(shù)在創(chuàng)建對(duì)象時(shí)執(zhí)行。

第一次嘗試可能是這樣的:

function myClass(func) {
 var myPrivateVar = Math.random();
 var reveal = function (){
      return myPrivateVar;
   }
 func();
}

這將創(chuàng)建一個(gè)設(shè)置為隨機(jī)值的私有變量浸卦,可以通過(guò)訪問(wèn)私有方法揭示來(lái)發(fā)現(xiàn)該私有變量署鸡。想法是func是一個(gè)傳遞給構(gòu)造函數(shù)然后執(zhí)行的函數(shù),可以利用reveal訪問(wèn)該值。

如果通過(guò)傳遞給它一個(gè)嘗試?yán)媒沂镜暮瘮?shù)來(lái)進(jìn)行嘗試:

var myObject = new myClass(
    function () { console.log(reveal()); }
);

當(dāng)調(diào)用 func 時(shí)靴庆,您將看到一條錯(cuò)誤消息时捌,提示 reveal 未定義。
這里的錯(cuò)誤是顯而易見(jiàn)的炉抒,表明不在傳遞給構(gòu)造函數(shù)的函數(shù)范圍內(nèi)奢讨。函數(shù)可以訪問(wèn)哪些變量取決于函數(shù)的聲明位置,而不是使用位置焰薄。解決該錯(cuò)誤的方法非常簡(jiǎn)單–將所需的私有成員作為參數(shù)傳遞給函數(shù)拿诸。
就是:

var myObject = new myClass(
  function (reveal) { console.log(reveal()); }
);

現(xiàn)在注意,該函數(shù)需要在構(gòu)造函數(shù)中使用參數(shù)進(jìn)行調(diào)用:

function myClass(func) {
  var myPrivateVar = Math.random();
  var reveal = function () { return myPrivateVar;};
  func(reveal);
}

現(xiàn)在一切正常塞茅。傳遞給構(gòu)造函數(shù)的函數(shù)可以調(diào)用私有函數(shù)亩码,只要它們?cè)谡{(diào)用函數(shù)時(shí)傳遞給私有函數(shù)即可。
一般原則是:

  • 對(duì)象的構(gòu)造函數(shù)中的局部變量以及內(nèi)部函數(shù)是該構(gòu)造函數(shù)及其構(gòu)造的對(duì)象的私有屬性野瘦。
  • 對(duì)象可以通過(guò)閉包訪問(wèn)這些私有變量蟀伸。
  • 通過(guò)傳遞參數(shù)調(diào)用構(gòu)造函數(shù)的代碼可以訪問(wèn)私有成員。
  • 如果調(diào)用構(gòu)造函數(shù)的代碼傳遞了由構(gòu)造函數(shù)執(zhí)行的函數(shù)缅刽,則此函數(shù)將無(wú)法訪問(wèn)私有變量啊掏,因?yàn)槎x函數(shù)時(shí)它們不在范圍內(nèi)。
  • 但是衰猛,可以在構(gòu)造函數(shù)調(diào)用函數(shù)時(shí)將私有變量傳遞給函數(shù)迟蜜,因?yàn)樗鼈冊(cè)谧饔糜騼?nèi)。
    注意啡省,您也可以這樣寫:
var myObject = new myClass(
  function (privateFunction) {
    console.log(privateFunction());
  }
);

該函數(shù)的名稱只是第一個(gè)參數(shù)傳遞的占位符娜睛。該函數(shù)實(shí)際的功能只有在構(gòu)造函數(shù)調(diào)用該函數(shù)時(shí)才變得固定。就是在那個(gè)時(shí)候:
func(reveal);
此模式通常用于允許外部代碼限制訪問(wèn)構(gòu)造函數(shù)中的私有函數(shù)卦睹,當(dāng)然畦戒,Promise構(gòu)造函數(shù)允許您訪問(wèn)resolve和reject函數(shù)。

承諾機(jī)制

創(chuàng)建標(biāo)準(zhǔn)Promise時(shí)结序,將使用其構(gòu)造函數(shù)障斋,并向其傳遞一個(gè)函數(shù)executor,該函數(shù)立即由構(gòu)造函數(shù)執(zhí)行徐鹤。此函數(shù)可用于創(chuàng)建異步任務(wù)鸯旁,然后相應(yīng)地調(diào)用resolve或reject-通常在異步任務(wù)完成時(shí)猛蔽。

換句話說(shuō),這是起作用的代碼。

例如脉漏,可以使用JavaScript Promises 延遲函數(shù)示例編寫為:

function delay(t) {
  var p = new Promise(
     function (resolve, reject) {
        setTimeout(
          function () {
             resolve();
          },
       t);
    });
  return p;
}

您可以看到它具有相同的基本結(jié)構(gòu)秩伞,唯一的區(qū)別是現(xiàn)在代碼調(diào)用了在構(gòu)造函數(shù)中定義的專用resolve和reject函數(shù)摄悯。構(gòu)造函數(shù)立即執(zhí)行此操作峡竣,將私有的resolve和reject函數(shù)傳遞給它秸谢,并返回Promise。

請(qǐng)注意霹肝,在傳遞給構(gòu)造函數(shù)的函數(shù)中估蹄,解析和拒絕的調(diào)用導(dǎo)致調(diào)用Promise使用者使用返回的Promise對(duì)象的then方法設(shè)置的所有onComplete和onError函數(shù)。僅在異步任務(wù)完成后才調(diào)用resolve或拒絕阿迈,并在resolve和reject中返回其值或錯(cuò)誤代碼元媚。
現(xiàn)在,我們可以理解上一章中介紹的示范Promise:

function delay(t, p) {
      var promise = new Promise(
                      function (resolve, reject) {
                         setTimeout(
                            function () {
                             var r = Math.random();
                             if (r > p) {
                               resolve(r);
                             } else {
                               reject(r);
                             }
                            },
                         t);
                      });
       return promise;
}

您可以看到發(fā)生了什么事苗沧,我們創(chuàng)建了一個(gè)新的Promise對(duì)象刊棕,該對(duì)象幾乎立即返回給調(diào)用者。我們還使用setTimeout在事件隊(duì)列上放置一個(gè)函數(shù)待逞,當(dāng)事件時(shí)間到時(shí)甥角,將以指定的概率調(diào)用resolve或reject函數(shù),將隨機(jī)數(shù)作為確定的值傳遞回去识樱。

要100%清除Promise構(gòu)造函數(shù)中使用的resolve和reject函數(shù)嗤无,是構(gòu)造函數(shù)提供的私有函數(shù)。揭示性的構(gòu)造器模式可確保這些值不能被構(gòu)造器或promise之外的任何其他代碼訪問(wèn)怜庸。

摘要

  • Promise旨在限制對(duì)解析和拒絕功能的訪問(wèn)当犯,而這些功能只能用于創(chuàng)建Promise的代碼。
  • 過(guò)去割疾,這是使用單獨(dú)的延遲對(duì)象(該對(duì)象保持私有狀態(tài))完成的嚎卫。
  • Promise標(biāo)準(zhǔn)利用揭示性的構(gòu)造函數(shù)模式來(lái)保持解析和拒絕私有,同時(shí)允許創(chuàng)建Promise的代碼向構(gòu)造函數(shù)提交使用它們的函數(shù)宏榕。
  • 揭示性構(gòu)造函數(shù)模式通過(guò)將私有變量傳遞給傳遞給構(gòu)造函數(shù)的函數(shù)拓诸,擴(kuò)展了閉包為構(gòu)造對(duì)象提供私有變量和函數(shù)的方式。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末麻昼,一起剝皮案震驚了整個(gè)濱河市奠支,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌抚芦,老刑警劉巖倍谜,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異燕垃,居然都是意外死亡枢劝,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門卜壕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人烙常,你說(shuō)我怎么就攤上這事轴捎『缀校” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵侦副,是天一觀的道長(zhǎng)侦锯。 經(jīng)常有香客問(wèn)我,道長(zhǎng)秦驯,這世上最難降的妖魔是什么尺碰? 我笑而不...
    開(kāi)封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮译隘,結(jié)果婚禮上亲桥,老公的妹妹穿的比我還像新娘。我一直安慰自己固耘,他們只是感情好题篷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著厅目,像睡著了一般番枚。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上损敷,一...
    開(kāi)封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天葫笼,我揣著相機(jī)與錄音,去河邊找鬼拗馒。 笑死路星,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的瘟忱。 我是一名探鬼主播奥额,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼访诱!你這毒婦竟也來(lái)了垫挨?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤触菜,失蹤者是張志新(化名)和其女友劉穎九榔,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涡相,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哲泊,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了催蝗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片切威。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖丙号,靈堂內(nèi)的尸體忽然破棺而出先朦,到底是詐尸還是另有隱情缰冤,我是刑警寧澤,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布喳魏,位于F島的核電站棉浸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏刺彩。R本人自食惡果不足惜迷郑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望创倔。 院中可真熱鬧嗡害,春花似錦、人聲如沸三幻。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)念搬。三九已至抑堡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間朗徊,已是汗流浹背首妖。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留爷恳,地道東北人有缆。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像温亲,于是被迫代替她去往敵國(guó)和親棚壁。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容