How to create a fulfilled promise in mpromise - javascript

I have a node#4.3.1 + mongo + mongoose#4.4.4 project which I think is providing me with the mpromise library (the mongoose docs imply this)
Assuming it is mpromise, I'm stumped by the very simple job of creating an already fulfilled promise (so I can stub a function that should return a promise).
The mpromise doc (see the "Chain" section) says I can do this:
function makeMeAPromise(i) {
var p = new Promise;
p.fulfill(i);
return p;
}
But this fails with the exception "Promise resolver undefined is not a function".
Am I using mpromise? Is the doc lying? How do I create a resolved promise?
edit: This works
return new Promise(function(fulfill, reject) { fulfill("really? this can't be the only way"); });
but that can't be the simplest way, right?

Mongo doesn't override the default Promise object in Node as far as I know. So the default ways should work just fine:
const resolvedPromise1 = new Promise(f => f("Fullfilled!"));
const resolvedPromise2 = Promise.resolve("Fullfilled!");

Related

Promise.defer standard?

I was working with Promises and prefer to use it like this:
function Deferred() {
this.resolve = null;
this.reject = null;
this.promise = new Promise(function(resolve, reject) {
this.resolve = resolve;
this.reject = reject;
}.bind(this));
Object.freeze(this);
}
function somethingAsync() {
var deferred = new Deferred();
// do stuff then deferred.resolve();
return deferred.promise;
}
I just came across though in Firefox Promise.defer() which gives me the same thing, is this standard? Or just specific to Firefox? I can't find it in the Promise docs of Firefox even - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Promise.defer was a suggestion at one point but it was decided to not include it in the spec but to instead include the promise constructor which uses the revealing constructor pattern.
It was implemented in Firefox and Chrome and later removed from Chrome. It is not a standard but was a proposal at one point.
Your usage of the promise constructor was explicitly supported as a use case when it was designed.
The reason the committee decided to go with the promise constructor was because it guards against synchronous throws by default:
new Promise((resolve, reject) => {
thisThrowsSynchronously();
});
Had the promise constructor not done this - you would have to potentially .catch and } catch(e) { on every promise returning function invocation which can be frustrating. The promise constructor establishes an invariant where .catch is sufficient.
I'd also like to point out that outside of converting callback APIs - I can count the number of times I've used the promise constructor on one hand. Typically your code should have close to zero deferreds or usages of the promise constructor.

Why does the Promise constructor need an executor?

When using Promises, why can't triggers for resolve and reject be defined elsewhere in the codebase?
I don't understand why resolve and reject logic should be localized where the promise is declared. Is this an oversight, or is there a benefit to mandating the executor parameter?
I believe the executor function should be optional, and that its existence should determine whether the promise encapsulates resolution or not. The promise would be much more extensible without such mandates, since you don't have to initiate async right away. The promise should also be resettable. It's a 1 shot switch, 1 or 0, resolve() or reject(). There are a multitude of parallel and sequential outcomes that can be attached: promise.then(parallel1) and promise.then(parallel2) and also promise.then(seq1).then(seq2) but reference-privileged players cannot resolve/reject INTO the switch
You can construct a tree of outcomes at a later time, but you can't alter them, nor can you alter the roots (input triggers)
Honestly, the tree of sequential outcomes should be edittable as well.. say you want to splice out one step and do something else instead, after you've declared many promise chains. It doesn't make sense to reconstruct the promise and every sequential function, especially since you can't even reject or destroy the promise either...
This is called the revealing constructor pattern coined by Domenic.
Basically, the idea is to give you access to parts of an object while that object is not fully constructed yet. Quoting Domenic:
I call this the revealing constructor pattern because the Promise constructor is revealing its internal capabilities, but only to the code that constructs the promise in question. The ability to resolve or reject the promise is only revealed to the constructing code, and is crucially not revealed to anyone using the promise. So if we hand off p to another consumer, say
The past
Initially, promises worked with deferred objects, this is true in the Twisted promises JavaScript promises originated in. This is still true (but often deprecated) in older implementations like Angular's $q, Q, jQuery and old versions of bluebird.
The API went something like:
var d = Deferred();
d.resolve();
d.reject();
d.promise; // the actual promise
It worked, but it had a problem. Deferreds and the promise constructor are typically used for converting non-promise APIs to promises. There is a "famous" problem in JavaScript called Zalgo - basically, it means that an API must be synchronous or asynchronous but never both at once.
The thing is - with deferreds it's possible to do something like:
function request(param) {
var d = Deferred();
var options = JSON.parse(param);
d.ajax(function(err, value) {
if(err) d.reject(err);
else d.resolve(value);
});
}
There is a hidden subtle bug here - if param is not a valid JSON this function throws synchronously, meaning that I have to wrap every promise returning function in both a } catch (e) { and a .catch(e => to catch all errors.
The promise constructor catches such exceptions and converts them to rejections which means you never have to worry about synchronous exceptions vs asynchronous ones with promises. (It guards you on the other side by always executing then callbacks "in the next tick").
In addition, it also required an extra type every developer has to learn about where the promise constructor does not which is pretty nice.
FYI, if you're dying to use the deferred interface rather than the Promise executor interface despite all the good reasons against the deferred interface, you can code one trivially once and then use it everywhere (personally I think it's a bad idea to code this way, but your volume of questions on this topic suggests you think differently, so here it is):
function Deferred() {
var self = this;
var p = this.promise = new Promise(function(resolve, reject) {
self.resolve = resolve;
self.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
if (p.finally) {
this.finally = p.finally.bind(p);
}
}
Now, you can use the interface you seem to be asking for:
var d = new Deferred();
d.resolve();
d.reject();
d.promise; // the actual promise
d.then(...) // can use .then() on either the Deferred or the Promise
d.promise.then(...)
Here a slightly more compact ES6 version:
function Deferred() {
const p = this.promise = new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
});
this.then = p.then.bind(p);
this.catch = p.catch.bind(p);
if (p.finally) {
this.finally = p.finally.bind(p);
}
}
Or, you can do what you asked for in your question using this Deferred() constructor:
var request = new Deferred();
request.resolve();
request.then(handleSuccess, handleError);
But, it has the downsides pointed out by Benjamin and is not considered the best way to code promises.

Is it possible to overwrite native Es6 promise resolve method?

I know that it's not the best approach to overwrite native JS API and I do it more for experiment.
I would like to overwrite Promise resolve method handler to do some extra logic on each resolve. Is it possible?
Yes, it's possible. You have to wrap Promise.prototype.then method.
Promise.prototype.then = (oldThen=>{
return function then(_successHandler, _rejectHandler){
/* your logic here;
remember: both successHandler and rejectHandler can be non-functions */
return oldThen.call(this, wrappedSuccessHandler, wrappedRejectHandler);
}
})(Promise.prototype.then);
This code won't be able to intercept new Promise() calls, but there is other workaround for this:
class SubPromise extends Promise {
constructor(executor) {
super(function(_resolve, _reject) {
/* your code goes here */
return executor(wrappedResolve, wrappedReject);
});
}
then(success, reject) {
return super.then(wrappedSuccessHandler, wrappedRejectHandler);
}
}
window.Promise = SubPromise;
It replaces global Promise property with your implementation, so all subsequent calls resolving to window.Promise will return your implementation.
See 25.4.5.3 Promise.prototype.then in spec for further details (with default handlers "thrower" and "identity").

Create a Promise object based on the current platform

I am using Apache Cordova and I've run into a multi-platform issue in regards to the Promise object.
Currently, I have to instantiate a promise like this:
var promise = new Promise(...) {
//Implementation
}
This is fine, however if the app is running on the Windows platform, I have to use WinJS instead. Like this:
var promise = new WinJS.Promise(...) {
//Implementation
}
This results in the following code:
var promise;
if (cordova.platformId == "windows") {
promise = new WinJS.Promise(...) {
//Implementation
}
}
else {
promise = new Promise(...) {
//Exactly the same implementation as above
}
}
The main issue here is that I am duplicating the implementation inside each promise, resulting in two blocks of code which is exactly the same. Therefore it's harder to maintain.
Is there a way I can instantiate the correct Promise based on the current platform without having to duplicate the code twice?
If Promise doesn't exist, you could just assign it to WinJS.Promise and then use Promise like you normally would.
Like:
if (typeof Promise === 'undefined' && cordova.platformId === 'windows') {
Promise = WinJS.Promise; // global assignment
}
// At this point you can use new Promise() as usual
As you develop in JS/Angular, why don't you use the Angular Promise?
I mean $q, an implementation of promises/deferred objects.
See Doc for $q

Can promises have multiple arguments to onFulfilled?

I'm following the spec here and I'm not sure whether it allows onFulfilled to be called with multiple arguments. For example:
promise = new Promise(function(onFulfilled, onRejected){
onFulfilled('arg1', 'arg2');
})
such that my code:
promise.then(function(arg1, arg2){
// ....
});
would receive both arg1 and arg2?
I don't care about how any specific promises implementation does it, I wish to follow the w3c spec for promises closely.
I'm following the spec here and I'm not sure whether it allows onFulfilled to be called with multiple arguments.
Nope, just the first parameter will be treated as resolution value in the promise constructor. You can resolve with a composite value like an object or array.
I don't care about how any specific promises implementation does it, I wish to follow the w3c spec for promises closely.
That's where I believe you're wrong. The specification is designed to be minimal and is built for interoperating between promise libraries. The idea is to have a subset which DOM futures for example can reliably use and libraries can consume. Promise implementations do what you ask with .spread for a while now. For example:
Promise.try(function(){
return ["Hello","World","!"];
}).spread(function(a,b,c){
console.log(a,b+c); // "Hello World!";
});
With Bluebird. One solution if you want this functionality is to polyfill it.
if (!Promise.prototype.spread) {
Promise.prototype.spread = function (fn) {
return this.then(function (args) {
return Promise.all(args); // wait for all
}).then(function(args){
//this is always undefined in A+ complaint, but just in case
return fn.apply(this, args);
});
};
}
This lets you do:
Promise.resolve(null).then(function(){
return ["Hello","World","!"];
}).spread(function(a,b,c){
console.log(a,b+c);
});
With native promises at ease fiddle. Or use spread which is now (2018) commonplace in browsers:
Promise.resolve(["Hello","World","!"]).then(([a,b,c]) => {
console.log(a,b+c);
});
Or with await:
let [a, b, c] = await Promise.resolve(['hello', 'world', '!']);
You can use E6 destructuring:
Object destructuring:
promise = new Promise(function(onFulfilled, onRejected){
onFulfilled({arg1: value1, arg2: value2});
})
promise.then(({arg1, arg2}) => {
// ....
});
Array destructuring:
promise = new Promise(function(onFulfilled, onRejected){
onFulfilled([value1, value2]);
})
promise.then(([arg1, arg2]) => {
// ....
});
The fulfillment value of a promise parallels the return value of a function and the rejection reason of a promise parallels the thrown exception of a function. Functions cannot return multiple values so promises must not have more than 1 fulfillment value.
As far as I can tell reading the ES6 Promise specification and the standard promise specification theres no clause preventing an implementation from handling this case - however its not implemented in the following libraries:
RSVP.promise (#L516-544)
Q promise (#787)
I assume the reason for them omiting multi arg resolves is to make changing order more succinct (i.e. as you can only return one value in a function it would make the control flow less intuitive) Example:
new Promise(function(resolve, reject) {
return resolve(5, 4);
})
.then(function(x,y) {
console.log(y);
return x; //we can only return 1 value here so the next then will only have 1 argument
})
.then(function(x,y) {
console.log(y);
});
De-structuring Assignment in ES6 would help here.For Ex:
let [arg1, arg2] = new Promise((resolve, reject) => {
resolve([argument1, argument2]);
});
Here is a CoffeeScript solution.
I was looking for the same solution and found seomething very intersting from this answer: Rejecting promises with multiple arguments (like $http) in AngularJS
the answer of this guy Florian
promise = deferred.promise
promise.success = (fn) ->
promise.then (data) ->
fn(data.payload, data.status, {additional: 42})
return promise
promise.error = (fn) ->
promise.then null, (err) ->
fn(err)
return promise
return promise
And to use it:
service.get().success (arg1, arg2, arg3) ->
# => arg1 is data.payload, arg2 is data.status, arg3 is the additional object
service.get().error (err) ->
# => err
Great question, and great answer by Benjamin, Kris, et al - many thanks!
I'm using this in a project and have created a module based on Benjamin Gruenwald's code. It's available on npmjs:
npm i -S promise-spread
Then in your code, do
require('promise-spread');
If you're using a library such as any-promise
var Promise = require('any-promise');
require('promise-spread')(Promise);
Maybe others find this useful, too!
Since functions in Javascript can be called with any number of arguments, and the document doesn't place any restriction on the onFulfilled() method's arguments besides the below clause, I think that you can pass multiple arguments to the onFulfilled() method as long as the promise's value is the first argument.
2.2.2.1 it must be called after promise is fulfilled, with promise’s value as its first argument.
To quote the article below, ""then" takes two arguments, a callback for a success case, and another for the failure case. Both are optional, so you can add a callback for the success or failure case only."
I usually look to this page for any basic promise questions, let me know if I am wrong
http://www.html5rocks.com/en/tutorials/es6/promises/

Categories