Why can't Promise.resolve be called as a function?

Something that overhears me and my colleague. Consider the following ...

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]);

      

As you would expect, header 1, 2, and 3 are outputted, as well as resolving promises 3, 4, and 5. But my question is, why the third soce? Why doesn't Promise.resolve behave like any other function?

[ 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)

      

+3


source to share


3 answers


Promise.resolve

refers to a function resolve

without a context object.

You want to call it with the appropriate context object. It can be done

  • by calling it on that context object as in v => Promise.resolve(v)

    , or
  • creating a linked version like in Promise.resolve.bind(Promise)

So this would work:

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

      


Remember Javascript has no classes. Functions have no owner. Objects can store functions in their properties, but this does not mean that the function belongs to that object.

Another way is to explicitly set the context object using Function#call

either Function#apply

:



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

      


This is perhaps best illustrated by focusing on something other than a method:

function Foo() {
    this.bar = {some: "value"};
    this.baz = function () { return this.bar; };
}

var f = new Foo();
var b = f.bar;
var z = f.baz;

      

here is b

referring to {some: "value"}

without {some: "value"}

magically "knowing" what f

stores a reference to it. This should be obvious.

The same is true for z

. It keeps the function without the function "knowing" that it is f

also referencing it. This should be just as obvious in theory.

The call z()

will give different results than the call f.baz()

, although the function called is the same. Only the context is different.

+8


source


When a function is called its this variable dynamically allocates a value .

The function resolve

takes care of what the value is.



The third part of your code passes a function resolve

and then calls it without an object context Promise

.

This means it this

does not get the highlighted value Promise

that the function requires.

+2


source


Promise.resolve

must be called with this

being a Promise constructor (or subclass).

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

      

So, change this line:

map(Promise.resolve)

      

in

map(Promise.resolve.bind(Promise))

      

+1


source







All Articles