Something that is bugging 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, the tan of 1, 2 and 3 are output and so are the promises resolving 3, 4 and 5. But my question is... why does the third break? Why doesn't Promise.resolve behave in the same way as 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)
Essentially, a promise is a returned object to which you attach callbacks, instead of passing callbacks into a function.
The Promise.resolve() method "resolves" a given value to a Promise . If the value is a promise, that promise is returned; if the value is a thenable, Promise.resolve() will call the then() method with two callbacks it prepared; otherwise the returned promise will be fulfilled with the value.
As a side note, we can return a promise from any function. It doesn't have to be asynchronous. That being said, promises are normally returned in cases where the function they return from is asynchronous. For example, an API that has methods for saving data to a server would be a great candidate to return a promise!
No. It is not safe to resolve/reject promise multiple times. It is basically a bug, that is hard to catch, becasue it can be not always reproducible.
Promise.resolve
refers to the resolve
function without context object.
You want to call it with the proper context object. This can be done
v => Promise.resolve(v)
, or Promise.resolve.bind(Promise)
So, this would work:
compose(
console.log,
map(Promise.resolve.bind(Promise))
)([7,8,9]);
Remember that Javascript does not have classes. Functions have no owner. Objects can store functions in their properties, but that does not mean the function is owned by that object.
Another way is setting the context object explicitly, with Function#call
or Function#apply
:
function (v) {
var resolve = Promise.resolve;
return resolve.call(Promise, v);
}
Maybe it's 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 b
refers to {some: "value"}
without {some: "value"}
magically "knowing" that f
stores a reference to it. This should be obvious.
The same is true of z
. It stores a function without that function "knowing" that f
also references it. This should be just as obvious, in theory.
Calling z()
will yield different results than calling f.baz()
, even though the called function is the same one. Only the context is different.
When a function is called its this variable is dynamically allocated a value.
The resolve
function cares what that value is.
The third part of your code passes the resolve
function and then calls it without the context of the Promise
object.
This means that this
does not get allocated the value of Promise
which the function needs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With