Skip to content

Instantly share code, notes, and snippets.

@dievardump
Last active August 29, 2015 14:15
Show Gist options
  • Save dievardump/aec07df630a15c76641e to your computer and use it in GitHub Desktop.
Save dievardump/aec07df630a15c76641e to your computer and use it in GitHub Desktop.
Really simple implementation of Promise - Not fully tested (catch was not)
var Promise = function(resolver) {
if (typeof resolver !== 'function') {
throw new Error('Promise constructor parameter must be a function.');
}
this._callbacks = [];
this._catchers = [];
this.running = true;
resolver(this.resolve.bind(this), this.reject.bind(this));
};
// run the next function in the pipe
Promise.prototype.run = function (toRun, args) {
var res = null,
self = this;
if (typeof toRun === 'function') {
self.running = true;
// catch errors
try {
res = toRun.apply(null, args);
} catch (e) {
this._caught(e);
}
if (res instanceof Promise) {
res.then(function (values) {
self.resolve(values);
});
} else {
self.resolve(res);
}
}
};
Promise.prototype.resolve = function() {
this.running = false;
var args = Array.prototype.slice.call(arguments),
next = this._getNextCallback();
this.run(next, args);
return this;
};
Promise.prototype.reject = function(err) {
if (this._catch) {
this._catch(err);
} else {
throw new Error(err);
}
return this;
};
Promise.prototype.then = function(callback) {
if (typeof callback !== 'function') {
throw new Error('Promise.then need a function as parameter.');
}
this._addCallback(callback);
if (!this.running) {
this.resolve();
}
return this;
};
Promise.prototype.catch = function(catcher) {
if (typeof catcher !== 'function') {
throw new Error('Promise.catch callback must be a function.');
}
var types = [];
if (arguments.length === 1) {
types = [Error];
} else {
var len = arguments.length, i = 0;
for(i = 0; i < len - 1; ++i) {
types.push(arguments[i]);
}
catcher = arguments[i];
}
types.forEach(function (type) {
if (type !== Error && !(type.prototype instanceof Error)) {
throw new Error('Promise.catch types must all be an Error type constructor.');
}
})
this._catchers.push({
types: types,
fn: catcher
});
return this;
};
Promise.prototype._caught = function (err) {
var catchers = this._catchers,
some = false;
for(var i = 0; i < catchers.length; i++) {
some = catchers[i].types.some(function (type) {
return (err instanceof type);
});
if (some) {
catchers[i].fn(err);
}
}
};
Promise.prototype._getNextCallback = function() {
var next = null;
if (this._callbacks.length) {
next = this._callbacks.shift();
}
return next;
};
Promise.prototype._addCallback = function(callback) {
this._callbacks.push(callback);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment