patternjavascriptMinor
Pledge: Promise-like entities design goals experiment
Viewed 0 times
designlikepromisegoalspledgeexperimententities
Problem
Background
I was writing a promises/a+ implementation, just for fun. About halfway through I decided it wasn't that fun after all, so I decided to do something a little different.
Thinking of promises as a pattern (and not a contract), I figured they basically amount to the following (if I'm missing the point, please correct me):
-
They "flatten" async* code, avoiding callback hell.
-
They allow sensible error handling on async code.
-
They are composable, and can be chained.
-
If one promise resolves to another, that new promise must also resolve before the rest of the chain resolves (e.g. a
* I get that promises themselves don't care about async, I'm thinking more about what people use them for.
Design goals
Instead of trying to conform to the promises/a+ spec, I decided to try to create something that would allow for using a similar pattern without worrying about the promise contract. I thought it would be interesting to learn:
-
Can something as powerful as promises can be implemented in a simpler / more minimal way?
-
What improvements can be made on a promise-like pattern?
-
Is it reasonable to try to integrate promises with other promise-like things?
The first two points basically boil down to ditching the design contract idea (having a special interface for everything that returns a promise) and making a system that works better with the more common function-takes-a-callback style interfaces.
The third point is handled by having "thenable" entities that work with
Promise-like entities
The Pledge API is similar to the Promises API.
Static methods
Use this instead of invoking the constructor.
-
Create a new pledge, return it, and resolve it after the current script finishes.
Instance methods
Use these on objects returned from
I was writing a promises/a+ implementation, just for fun. About halfway through I decided it wasn't that fun after all, so I decided to do something a little different.
Thinking of promises as a pattern (and not a contract), I figured they basically amount to the following (if I'm missing the point, please correct me):
-
They "flatten" async* code, avoiding callback hell.
-
They allow sensible error handling on async code.
-
They are composable, and can be chained.
-
If one promise resolves to another, that new promise must also resolve before the rest of the chain resolves (e.g. a
then function returning a promise).* I get that promises themselves don't care about async, I'm thinking more about what people use them for.
Design goals
Instead of trying to conform to the promises/a+ spec, I decided to try to create something that would allow for using a similar pattern without worrying about the promise contract. I thought it would be interesting to learn:
-
Can something as powerful as promises can be implemented in a simpler / more minimal way?
-
What improvements can be made on a promise-like pattern?
-
Is it reasonable to try to integrate promises with other promise-like things?
The first two points basically boil down to ditching the design contract idea (having a special interface for everything that returns a promise) and making a system that works better with the more common function-takes-a-callback style interfaces.
The third point is handled by having "thenable" entities that work with
Promise.resolve, and by recognizing and resolving other "thenables" passed from one entity to another.Promise-like entities
The Pledge API is similar to the Promises API.
Static methods
Use this instead of invoking the constructor.
-
Pledge.resolve(callback)Create a new pledge, return it, and resolve it after the current script finishes.
Instance methods
Use these on objects returned from
Pledge.create and Pledge.resolve.Solution
Very interesting question.
From a high level perspective, the code gets a bit hairy from
I really only have nitpickings;
-
This code could have been shorter if the Pledge constructor could take the
could be
-
This: in a format suitable for an argument passed to a vow function. and this
-
I got stuck on this:
consider writing this for readability
especially since you use compiler afterwards
-
In
and
All in all, I like the code, it is more readable than other Promise libraries that I tried to grok.
From a high level perspective, the code gets a bit hairy from
Internal stuff on, which means the API is quite clear.I really only have nitpickings;
-
This code could have been shorter if the Pledge constructor could take the
vows parameter:function create(vows) {
var pledge = new Pledge();
pledge.vows = vows;
return pledge;
}could be
function create(vows) {
return new Pledge( vows );
}-
This: in a format suitable for an argument passed to a vow function. and this
if (value.length == 1) { value = value[0]; drive me nuts. I dont understand from the code why you need this, and the comments are not helping me understand this either. You have this array shifting in both argValue and listValue, you could have a common helper function here-
I got stuck on this:
return self.vows && self.vows.length || 0;consider writing this for readability
return ( self.vows && self.vows.length ) || 0;especially since you use compiler afterwards
-
In
setReady(self), the naming could be better, if self is a pledge, why not call the parameter pledge ? Since a pledge has vows why not call completion -> vow. Compare and contrastfunction setReady(self) {
var completion;
self.ready = true;
while ((completion = self.pending.pop())) {
completion();
}
}and
function setReady(pledge) {
var vow;
pledge.ready = true;
while ((vow = pledge.pending.pop())) {
vow();
}
}- In
resolveArgsas well, I would replaceselfwithpledge, things become far more clearer.
All in all, I like the code, it is more readable than other Promise libraries that I tried to grok.
Code Snippets
function create(vows) {
var pledge = new Pledge();
pledge.vows = vows;
return pledge;
}function create(vows) {
return new Pledge( vows );
}return self.vows && self.vows.length || 0;return ( self.vows && self.vows.length ) || 0;function setReady(self) {
var completion;
self.ready = true;
while ((completion = self.pending.pop())) {
completion();
}
}Context
StackExchange Code Review Q#51710, answer score: 3
Revisions (0)
No revisions yet.