Skip to content

Instantly share code, notes, and snippets.

@spencercwood
Last active January 3, 2018 23:57
Show Gist options
  • Select an option

  • Save spencercwood/d7f2b3a771d555a8a35de6aa2b2992a7 to your computer and use it in GitHub Desktop.

Select an option

Save spencercwood/d7f2b3a771d555a8a35de6aa2b2992a7 to your computer and use it in GitHub Desktop.
Simple (?) promise implementation, definitely not spec compliant
class SimplePromise {
static resolve(value) {
return new SimplePromise((resolve) => resolve(value));
}
static reject(value) {
return new SimplePromise((resolve, reject) => reject(value));
}
// fixme
static all(promises) {
return new SimplePromise((resolve, reject) => {
const results = [];
let numberFinished = 0;
let rejected = false;
promises.forEach((p, i) => {
p.then((r) => {
results[i] = r;
if (++numberFinished === promises.length && !rejected) {
resolve(results);
}
}).catch((e) => {
rejected = true;
reject(e);
});
});
});
}
constructor(originalFunction) {
this._thens = [];
this._catches = [];
this._callbackCount = 0;
this._currentCallbackNumber = 0;
this.then = this.then.bind(this);
this.catch = this.catch.bind(this);
this._onResolve = this._onResolve.bind(this);
this._onReject = this._onReject.bind(this);
setTimeout(() => {
return originalFunction(this._onResolve, this._onReject);
}, 0);
}
then(onFulfilled, onRejected) {
if (onFulfilled) {
this._thens.push([++this._callbackCount, onFulfilled]);
}
if (onRejected) {
this._catches.push([++this._callbackCount, onRejected]);
}
return this;
}
catch(onRejected) {
this.then(null, onRejected);
return this;
}
_onResolve(result) {
if (this._thens.length === 0) {
return;
}
const [number, callback] = this._thens.shift();
this._currentCallbackNumber = number;
let newResult;
try {
newResult = callback(result);
} catch (error) {
this._onReject(error);
return;
}
if (newResult instanceof SimplePromise) {
newResult
.then(this._onResolve)
.catch(this._onReject);
return;
}
this._onResolve(newResult);
}
_onReject(error) {
if (this._catches.length === 0) {
return;
}
const [number, callback] = this._catches.shift();
if (number < this._currentCallbackNumber) {
this._onReject(error);
return;
}
callback(error);
this._onReject(error);
}
}
module.exports = SimplePromise;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment