【问题标题】:Why can't Promise.resolve be called as a function?为什么 Promise.resolve 不能作为函数调用?
【发布时间】:2017-12-25 21:07:10
【问题描述】:

困扰着我和我的同事的事情。考虑以下...

const {map, compose} = require('ramda');

compose(
  console.log,
  map(Math.tan)
)([1,2,3]);

compose(
  console.log,
  map(v=>Promise.resolve(v))
)([4,5,6]);

compose(
  console.log,
  map(Promise.resolve)
)([7,8,9]);

如您所料,输出 1、2 和 3 的棕褐色,解析 3、4 和 5 的承诺也是如此。但我的问题是……为什么第三个会中断?为什么 Promise.resolve 的行为方式与任何其他函数不同?

[ 1.5574077246549023, -2.185039863261519, -0.1425465430742778 ]
[ Promise { 4 }, Promise { 5 }, Promise { 6 } ]
/home/xxx/node_modules/ramda/src/internal/_map.js:6
    result[idx] = fn(functor[idx]);
                  ^

TypeError: PromiseResolve called on non-object
    at resolve (<anonymous>)
    at _map (/home/xxx/node_modules/ramda/src/internal/_map.js:6:19)
    at map (/home/xxx/node_modules/ramda/src/map.js:57:14)
    at /home/xxx/node_modules/ramda/src/internal/_dispatchable.js:39:15
    at /home/xxx/node_modules/ramda/src/internal/_curry2.js:20:46
    at f1 (/home/xxx/node_modules/ramda/src/internal/_curry1.js:17:17)
    at /home/xxx/node_modules/ramda/src/internal/_pipe.js:3:27
    at /home/xxx/node_modules/ramda/src/internal/_arity.js:5:45
    at Object.<anonymous> (/home/xxx/b.js:20:6)
    at Module._compile (module.js:569:30)

【问题讨论】:

    标签: javascript functional-programming promise ramda.js


    【解决方案1】:

    Promise.resolve 指的是resolve 函数没有上下文对象

    你想用正确的上下文对象来调用它。这是可以做到的

    • 通过在该上下文对象上调用它,如v =&gt; Promise.resolve(v),或
    • 通过创建它的绑定版本,如Promise.resolve.bind(Promise)

    所以,这会起作用:

    compose(
      console.log,
      map(Promise.resolve.bind(Promise))
    )([7,8,9]);
    

    请记住,Javascript 没有类。函数没有所有者。对象可以在其属性中存储函数,但这并不意味着该函数归该对象所有。

    另一种方法是显式设置上下文对象,使用Function#callFunction#apply

    function (v) {
        var resolve = Promise.resolve;
        return resolve.call(Promise, v);
    }
    

    也许最好通过关注方法以外的东西来说明这一点:

    function Foo() {
        this.bar = {some: "value"};
        this.baz = function () { return this.bar; };
    }
    
    var f = new Foo();
    var b = f.bar;
    var z = f.baz;
    

    这里b 指的是{some: "value"} 而没有{some: "value"} 神奇地“知道”f 存储了对它的引用。这应该是显而易见的。

    z 也是如此。它存储了一个函数,而该函数“知道”f 也引用了它。从理论上讲,这应该同样明显。

    调用z() 将产生与调用f.baz() 不同的结果,即使调用的函数是相同的。只是上下文不同。

    【讨论】:

    • 非常感谢。它开始变得更有意义,但我认为这是我将要消化的东西。我一直在尝试将函数创建为函数对象的属性。试图了解如何首先调用 resolve()。
    【解决方案2】:

    当一个函数被调用时,它的this variable is dynamically allocated a value.

    resolve 函数关心该值是什么。

    代码的第三部分传递resolve 函数,然后在没有Promise 对象的上下文的情况下调用它。

    这意味着this 没有得到函数需要的Promise 的值。

    【讨论】:

    • 感谢昆汀的回复。这真的很有帮助。我注意到 typeof Math 是一个对象,而 typeof Promise 是一个帮助我尝试和理解的函数(构造函数)。
    【解决方案3】:

    Promise.resolve 需要被调用,this 是 Promise 构造函数(或子类)。

    resolve = Promise.resolve;
    resolve(null); // Error
    resolve.call({}); // Error: Object is not a constructor
    

    所以改变这一行:

    map(Promise.resolve)
    

    到:

    map(Promise.resolve.bind(Promise))
    

    【讨论】:

    • 谢谢金登。 Promise.resolve.bind(Promise) 真的很有趣。这会让我头晕目眩。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-30
    • 2021-09-03
    • 2017-04-04
    • 2021-10-12
    • 1970-01-01
    • 2021-04-23
    相关资源
    最近更新 更多