Created
July 7, 2017 16:44
-
-
Save tannerwelsh/5236252ffacfb0867e65269f4a4547b7 to your computer and use it in GitHub Desktop.
Reverse-engineering Promise (loosely)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is a very bare-bones (and incomplete) implementation of the idea | |
// behind Promise, using a new function called Commitment: | |
const Commitment = function(func) { | |
this.state = 'PENDING' // will be changed to 'FULFILLED' or 'REJECTED' | |
const resolve = (result) => { | |
this.state = 'FULFILLED' | |
this.resolver && this.resolver(result) | |
} | |
const reject = (error) => { | |
this.state = 'REJECTED' | |
this.rejecter && this.rejecter(error) | |
} | |
func(resolve, reject) | |
} | |
Commitment.prototype.then = function(callback) { | |
this.resolver = callback | |
return this | |
} | |
Commitment.prototype.catch = function(callback) { | |
this.rejecter = callback | |
return this | |
} | |
// --- Example usage below --- | |
// This function will serve as our asynchronous code that the Commitment will wrap | |
// Uncomment the `throw Error('Oh no!')` to trigger the `catch` part of the Commitment | |
const asyncFunc = (resolve, reject) => { | |
setTimeout(() => { | |
try { | |
// code that could throw an error | |
// throw Error('Oh no!') | |
} catch (err) { | |
return reject(err) | |
} | |
return resolve('Success!') | |
}, 1000) | |
} | |
// Test out our Commitment with an asynchronous function! | |
const longFunc = new Commitment(asyncFunc) | |
// Set up some monitoring to show the change in state | |
const logState = () => console.log(`Current state of longFunc: ${longFunc.state}`) | |
const monitor = setInterval(logState, 200) | |
longFunc.then((result) => { | |
clearInterval(monitor) | |
logState() | |
console.log(result) | |
}) | |
longFunc.catch((err) => { | |
clearInterval(monitor) | |
logState() | |
console.error(err) | |
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This is how the Promise feature works in normal JS | |
// This function will serve as our asynchronous code that the Promise will wrap | |
// Uncomment the `throw Error('Oh no!')` to trigger the `catch` part of the Promise | |
const asyncFunc = (resolve, reject) => { | |
setTimeout(() => { | |
try { | |
// code that could throw an error | |
// throw Error('Oh no!') | |
} catch (err) { | |
return reject(err) | |
} | |
return resolve('Success!') | |
}, 1000) | |
} | |
// Using a Promise object, we can attach handlers for success (with `then()`) | |
// and failure (with `catch()`) | |
const longFunc = new Promise(asyncFunc) | |
longFunc.then((result) => { | |
console.log(result) | |
}) | |
longFunc.catch((err) => { | |
console.error(err) | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is great. A couple weeks ago, I was trying to figure this out myself -- and was having trouble knowing where to start. Then, I found your code! I tried to add functionality for chaining
.then()
calls as well as doing synchronous actions. I'd be curious what you think:https://codepen.io/andrewgibson/pen/rwQrpd