Skip to content

Instantly share code, notes, and snippets.

@BGR360
Last active October 31, 2017 03:15
Show Gist options
  • Save BGR360/b13af798edfd8c21fa57572b38a42919 to your computer and use it in GitHub Desktop.
Save BGR360/b13af798edfd8c21fa57572b38a42919 to your computer and use it in GitHub Desktop.
Implementation of DeOrio's Promise class from Lecture 10
/**
* This is an implementation of a Promise class that works identically
* to the Promise class that DeOrio uses in lecture. Hopefully this can help
* you further understand how a Promise class works.
*
* Lots of love,
* Ren Beeves <3
*
* NOTE: I am not sure if this properly handles error propagation.
*/
class Promise {
constructor(executor) {
// These are the callbacks that the Promise will call
// when the promise is either resolved or encounters an error.
this.onresolve = null;
this.onerror = null;
// The next Promise in the chain (actually, the resolve function
// for the next promise in the chain)
this.next = null;
// Stupid ES6 binding
this.then = this.then.bind(this);
this.catch = this.catch.bind(this);
// When the user creates a new Promise object, they must provide
// an executor function. The executor function sets up the
// asynchronous operation.
// We, the Promise, call that executor function with two parameters:
// 1) A resolve function that the user can call to resolve the promise
// 2) A reject function that the user can call to reject the promise
function userResolveFunc() {
// Add a function to the event queue that will:
// 1) Call the user's onresolve callback
// 2) Resolve the next Promise in the chain (if there is one)
// using the result of the user's callback
if (this.onresolve) {
const resolveFunc = () => {
// 1) call user's callback
const returnValue = this.onresolve(value);
// 2) resolve the next Promise in the chain
if (this.next) {
this.next(returnValue);
}
};
setTimeout(resolveFunc, 0);
}
}
function userRejectFunc() {
// Add call to this.onerror() to the event queue
if (this.onerror) {
const rejectFunc = () => { this.onerror(err); };
setTimeout(rejectFunc, 0);
}
}
// Call the user's executor function
executor(userResolveFunc, userRejectFunc);
}
/**
* Sets the onresolve callback for this promise. If the user never
* calls then() on this Promise, it will simply do nothing when the
* promise is resolved.
*/
then(callback) {
// Now we know which function to call when this Promise gets resolved
this.onresolve = callback;
// Create a Promise to act as the next in the chain (if the user wants)
const nextPromise = new Promise((resolve) => {
// When the original Promise gets resolved, we call this.onresolve,
// and then we'll call nextPromise's resolve()
this.next = resolve;
});
return nextPromise;
}
/**
* Sets the onerror callback for this promise. If the user never
* calls catch() on this Promise, it will have nowhere to send
* any errors to.
*/
catch(callback) {
this.onerror = callback;
}
}
/**
* This is the wait() example from lecture 10,
* but with an additional 'result' param.
*
* Waits for ms milliseconds and then returns result asynchronously.
*
* @param ms Number of milliseconds to wait before resolving the promise
* @param result The result to return after ms milliseconds
* @returs A Promise that will resolve after ms milliseconds
*/
function wait(ms, result) {
return new Promise((resolve, reject) => {
// Call resolve() on the promise after ms milliseconds
setTimeout(() => {
resolve(result);
}, ms);
});
}
// Use the wait function
// Output should be:
// this is the result
// 42
wait(1000, "this is the result")
.then((result) => {
// result === "this is the result"
console.log(result);
return 42;
})
.then((transformedResult) => {
console.log(transformedResult);
})
.catch((err) => {
console.error(err);
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment