【问题标题】:promise-like objects and then-able duck typing in javascript promise类似 promise 的对象,然后可以在 javascript promise 中输入鸭子
【发布时间】:2017-08-29 02:15:00
【问题描述】:

我目前正在学习 JavaScript promise

我被告知,如果一个对象/函数本身包含一个名为 then(..) 的成员函数,那么该对象/函数将被识别为 promise like object,无论该对象/函数是真正的 promise 对象还是不是。

所以我想出了以下代码。

var aPromise = new Promise(function (resolve, reject){});
aPromise instanceof Promise; //prints true in chrome console


var a = {
    then: function(){}
};

a instanceof Promise;

但是a instanceof Promise 在 chrome 控制台中执行后,false 被打印出来了。

为什么会这样?是我做错了什么,还是我对什么是类 Promise 对象的理解不正确?

【问题讨论】:

  • “Promise-like object”意味着尽管 不是 a instanceof Promise, a 可以被视为一个承诺。
  • 我认为这意味着它将像一个承诺一样行事,但不一定是它的一个实例。因为它的行为就像一个,但实际上仍然只是一个对象。
  • it will act like a promise - 希望,因为不能保证 .then 函数必须做任何类似的承诺:p
  • 任何不是 Promise 的东西都会导致 a instance Promise 为 false ...即使是那些没有 .then ...instanceof 的也不关心 thenables
  • instanceof 顾名思义测试一个对象是否是某个构造函数的实例。由于您的 a 不是由 Promise 构造函数创建的,也不是从它继承的函数,因此它不是它的实例。如果您想测试“promise like”或“thenable”,请测试thenif('then' in a)

标签: javascript asynchronous promise


【解决方案1】:

A. instanceof

从技术上讲,Javascript 表达式 a instanceof b 检查

  • a 是一个对象(包括函数,因为它们是对象),
  • 'b' 是一个构造函数 - 它包括类,因为使用 class 关键字的声明和表达式会创建构造函数,
  • b.prototype 的值在a 的继承链中。这意味着a 是由b 构造的,或者在a 的继承链中的某个位置有一个由b 构造的对象。

假设对象继承链设置为其构造函数的prototype 属性,您的代码中的aPromisePromise 的一个实例,因为Promise.prototype 是其原型链中的第一个条目。其原型链中的第二个条目是Object.prototype,所以aPromise 也是Object 的一个实例。

aObject 构造和初始化,以响应{..} 对象初始化器语法。 Object.prototype 是其继承中的第一个对象,因此它是Object 的“实例”,仅此而已。

B. Thenable 对象

带有.then 方法的“Thenable”对象在A+ promise specification 中进行了描述,ES6 Promise 正是基于该方法。

thenables 的识别和处理允许不同的软件库(每个库使用自己的 Promise 构造函数代码)来处理由使用不同构造函数创建的另一个库创建的 Promise。简单地检查一个 Promise 对象是否是库自己的“Promise”构造函数的一个实例,可以防止库间使用 Promise 对象。

promise 实现需要处理“thenable”对象的一次是使用外部库 promise 来解析实现创建的 promise。处理这个问题的标准方法是让实现创建一对新的解析/拒绝函数,比如 resolve2reject2 用于正在解析的承诺,并调用 thenable 的 then 方法来传递它的结算值.在伪代码中:

if promiseA, instance of PromiseA, is resolved with promiseB, instance of PromiseB {

    PromiseA code creates new resolve2/reject2 functions for promiseA
    and calls the thenable's then method as:

         promiseB.then( resolve2, reject2);
}
// ....
If promiseB remains pending, promiseA remains pending;
If promiseB is settled, promiseA becomes fulfilled or rejected with the same value.

【讨论】:

    【解决方案2】:

    如果你想检查一个 thenable (Promise like) 对象

    if ((typeof a === 'function' || typeof a === 'object') && typeof a.then === 'function') {
        // a is "Promise like" (or a Promise)
    }
    

    【讨论】:

      【解决方案3】:

      instanceof 操作符测试一个对象是否在其原型链中 具有构造函数的原型属性。

      https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof

      这与鸭子类型无关(甚至可能相反?),其中对象的方法和属性决定对象的语义,从而允许您对待就像您可能会对待 Promise 一样,但它绝不会使其成为 Promise 的实例或后代。

      我添加的重点

      在使用面向对象编程语言的计算机编程中, 鸭子类型是一种类型的类型,其中对象的方法和 属性决定了有效的语义,而不是它的 从特定类或特定实现的继承 界面

      https://en.wikipedia.org/wiki/Duck_typing 通过https://ericlippert.com/2014/01/02/what-is-duck-typing/

      javascript 中的一个具体示例是nodeList;它类似于数组,因为您可以通过整数索引访问节点列表的成员,但它不是数组,也不是 instanceof 数组。

      【讨论】:

        【解决方案4】:

        使用 Promise.resolve 方法将 thenable 对象 ('a') 转换为 Promise:

        var a = Promise.resolve({
            then: function(){}
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2023-03-09
          • 1970-01-01
          • 2016-03-26
          • 2021-11-03
          • 2017-02-13
          • 1970-01-01
          • 2018-03-06
          • 1970-01-01
          相关资源
          最近更新 更多