Skip to content

Instantly share code, notes, and snippets.

@jacobgardner
Last active February 8, 2017 19:15
Show Gist options
  • Save jacobgardner/748610f0a9222171e3b7f5b05e0ca86f to your computer and use it in GitHub Desktop.
Save jacobgardner/748610f0a9222171e3b7f5b05e0ca86f to your computer and use it in GitHub Desktop.
class Promise {
triggered?: string;
resultOrReason: any;
rejectHandlers: Function[];
resolveHandlers: Function[];
constructor(callback: (resolve, reject?) => void) {
this.triggered = null;
this.rejectHandlers = [];
this.resolveHandlers = [];
this._reject = this._reject.bind(this);
this._resolve = this._resolve.bind(this);
callback(this._resolve, this._reject);
}
private _resolve(value?): void {
// resolve all the thens
if (!this.triggered) {
const handleResolve = (value?) => {
this.resolveHandlers.forEach((handler) => {
handler(value);
});
}
if (value instanceof Promise) {
this.triggered = 'pending';
value.then((value?) => {
this.triggered = 'resolve';
this.resultOrReason = value;
handleResolve(value);
}).catch((err?) => {
this.rejectHandlers.forEach((handler) => {
handler(err);
});
});
} else {
this.triggered = 'resolve';
this.resultOrReason = value;
handleResolve(value);
}
}
}
private _reject(reason?): void {
// Resolve all the rejects. If no reject, fall through
if (!this.triggered) {
this.triggered = 'reject';
this.resultOrReason = reason;
this.rejectHandlers.forEach((handler) => {
handler(this.resultOrReason);
});
}
}
static resolve(value?): Promise {
return new Promise((resolve) => {
resolve(value);
});
}
static reject(reason?): Promise {
return new Promise((resolve, reject) => {
reject(reason);
});
}
static all(promises): Promise {
return new Promise((resolve, reject) => {
const output = [];
let completed = 0;
promises.forEach((promise, idx) => {
promise.then((value) => {
output[idx] = value;
completed += 1;
if (completed === promises.length) {
resolve(output);
}
}).catch(reject);
});
});
}
then(resolveHandler?, rejectHandler?): Promise {
return new Promise((resolve, reject) => {
const resolver = (value?) => {
try {
if (!resolveHandler) {
resolve(value);
} else {
resolve(resolveHandler(value));
}
} catch (err) {
reject(err);
}
};
const rejecter = (reason?) => {
try {
if (!rejectHandler) {
// Falls through if failed
reject(reason);
} else {
resolve(rejectHandler(reason));
}
} catch (err) {
reject(err);
}
}
if (this.triggered === 'resolve') {
resolver(this.resultOrReason);
} else if (this.triggered === 'reject') {
rejecter(this.resultOrReason);
} else {
this.resolveHandlers.push(resolver);
this.rejectHandlers.push(rejecter);
}
});
}
catch(rejectHandler): Promise {
return this.then(null, rejectHandler);
}
}
const request = require('request');
function websiteGetter(uri) {
return new Promise((resolve, reject) => {
request(uri, (err, response) => {
if (err) { return reject(err); }
resolve(response);
});
});
}
const p = websiteGetter('http://google.com');
p.then((result) => {
// throw new Error('Whoopsie');
return websiteGetter('http://twitter.com');
}).then((result) => {
console.log(result.body);
}).catch((err) => {
console.log(err.message);
});
console.log('Done');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment