Promise 的 revealing-constructor

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

概念解析:
revealing-constructor pattern

揭示性的建构模式

Promise 对构造函数提供私有方法(显示构造函数模式)的标准方式进行了修改。
私有方法是在创建对象时作为闭包创建的方法。这是用于创建可从对象内部而不是外部访问的私有变量的标准方法。唯一的区别是变量引用了一个函数。如:

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

这是仅使用一种方法myFunction的对象的构造函数。
重要的部分是称为private的变量。这不是对象的一部分,因为它没有声明为对象的属性。因此,如果您尝试:

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

您将看到一个不存在 private 的错误。但是,由于在声明 myFunction 时在范围内是private,因此可以将其作为闭包使用:

myObject.myFunction();

确实显示private的值。

私有方法使用相同的机制,所不同的是变量引用了一个函数-一个内部函数,该内部函数不是正在构造的对象的方法。
这是JavaScript Promise用来解析和拒绝私有方法的机制,但有一些其他的变化。

私有函数和变量由传递给构造函数的函数访问。
让我们看看它是如何工作的。
假设您需要将私有变量设置为某个值,但仅在使用构造函数时才需要。
最简单的解决方案是:

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

现在,您可以使用以下方法创建实例:

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

将打印私有变量的值,即10,并且在使用构造函数时已设置了该变量,但是该变量现在无法通过对象外部的代码进行更改。
这似乎很简单,但是如果我们进一步推动这个想法,就会变得更加困难。

如果要在构造函数调用中传递与正在构造的对象的私有成员一起使用的函数,会发生什么情况?该函数旨在由构造函数在创建对象时执行。

第一次尝试可能是这样的:

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

这将创建一个设置为随机值的私有变量,可以通过访问私有方法揭示来发现该私有变量。想法是func是一个传递给构造函数然后执行的函数,可以利用reveal访问该值。

如果通过传递给它一个尝试利用揭示的函数来进行尝试:

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

当调用 func 时,您将看到一条错误消息,提示 reveal 未定义。
这里的错误是显而易见的,表明不在传递给构造函数的函数范围内。函数可以访问哪些变量取决于函数的声明位置,而不是使用位置。解决该错误的方法非常简单–将所需的私有成员作为参数传递给函数。
就是:

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

现在注意,该函数需要在构造函数中使用参数进行调用:

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

现在一切正常。传递给构造函数的函数可以调用私有函数,只要它们在调用函数时传递给私有函数即可。
一般原则是:

  • 对象的构造函数中的局部变量以及内部函数是该构造函数及其构造的对象的私有属性。
  • 对象可以通过闭包访问这些私有变量。
  • 通过传递参数调用构造函数的代码可以访问私有成员。
  • 如果调用构造函数的代码传递了由构造函数执行的函数,则此函数将无法访问私有变量,因为定义函数时它们不在范围内。
  • 但是,可以在构造函数调用函数时将私有变量传递给函数,因为它们在作用域内。
    注意,您也可以这样写:
var myObject = new myClass(
  function (privateFunction) {
    console.log(privateFunction());
  }
);

该函数的名称只是第一个参数传递的占位符。该函数实际的功能只有在构造函数调用该函数时才变得固定。就是在那个时候:
func(reveal);
此模式通常用于允许外部代码限制访问构造函数中的私有函数,当然,Promise构造函数允许您访问resolve和reject函数。

承诺机制

创建标准Promise时,将使用其构造函数,并向其传递一个函数executor,该函数立即由构造函数执行。此函数可用于创建异步任务,然后相应地调用resolve或reject-通常在异步任务完成时。

换句话说,这是起作用的代码。

例如,可以使用JavaScript Promises 延迟函数示例编写为:

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

您可以看到它具有相同的基本结构,唯一的区别是现在代码调用了在构造函数中定义的专用resolve和reject函数。构造函数立即执行此操作,将私有的resolve和reject函数传递给它,并返回Promise。

请注意,在传递给构造函数的函数中,解析和拒绝的调用导致调用Promise使用者使用返回的Promise对象的then方法设置的所有onComplete和onError函数。仅在异步任务完成后才调用resolve或拒绝,并在resolve和reject中返回其值或错误代码。
现在,我们可以理解上一章中介绍的示范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;
}

您可以看到发生了什么事,我们创建了一个新的Promise对象,该对象几乎立即返回给调用者。我们还使用setTimeout在事件队列上放置一个函数,当事件时间到时,将以指定的概率调用resolve或reject函数,将随机数作为确定的值传递回去。

要100%清除Promise构造函数中使用的resolve和reject函数,是构造函数提供的私有函数。揭示性的构造器模式可确保这些值不能被构造器或promise之外的任何其他代码访问。

摘要

  • Promise旨在限制对解析和拒绝功能的访问,而这些功能只能用于创建Promise的代码。
  • 过去,这是使用单独的延迟对象(该对象保持私有状态)完成的。
  • Promise标准利用揭示性的构造函数模式来保持解析和拒绝私有,同时允许创建Promise的代码向构造函数提交使用它们的函数。
  • 揭示性构造函数模式通过将私有变量传递给传递给构造函数的函数,扩展了闭包为构造对象提供私有变量和函数的方式。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335

推荐阅读更多精彩内容