Skip to content

Instantly share code, notes, and snippets.

@kaustubh-karkare
Last active August 25, 2019 00:41
Show Gist options
  • Save kaustubh-karkare/ea29d2b7fec4b58fb9ebe7fd1cf15d28 to your computer and use it in GitHub Desktop.
Save kaustubh-karkare/ea29d2b7fec4b58fb9ebe7fd1cf15d28 to your computer and use it in GitHub Desktop.
Educational reimplementation.
class Promise2 {
PENDING = 0;
FULFILLED = 1;
REJECTED = 2;
static resolve(value) {
return new Promise2((resolve, reject) => resolve(value));
}
static reject(value) {
return new Promise2((resolve, reject) => reject(value));
}
constructor(method) {
this.status = this.PENDING;
this.value_or_error = undefined;
this._then_callbacks = [];
this._catch_callbacks = [];
method(this._resolve.bind(this), this._reject.bind(this));
}
_resolve(value) {
if (this.status == this.PENDING) {
this.status = this.FULFILLED;
this.value_or_error = value;
this._flush(this._then_callbacks, value);
this._catch_callbacks = [];
}
}
_reject(error) {
if (this.status == this.PENDING) {
this.status = this.REJECTED;
this.value_or_error = error;
this._then_callbacks = [];
this._flush(this._catch_callbacks, error);
}
}
_flush(queue, ...args) {
while (queue.length) queue.pop(0)(...args);
}
then(then_method = undefined, catch_method = undefined) {
const original = this;
const next_promise = new Promise2(function(resolve, reject) {
[
{method: then_method || resolve, callbacks: original._then_callbacks},
{method: catch_method || reject, callbacks: original._catch_callbacks},
].forEach(function({method, callbacks}) {
callbacks.push(value_or_error => {
try {
var result = method(value_or_error);
} catch (next_error) {
reject(next_error);
return;
}
if (result instanceof Promise2) {
result.then(
next_value => resolve(next_value),
next_error => reject(next_error),
);
} else {
resolve(result);
}
});
});
});
if (this.status == this.FULFILLED) {
this._flush(this._then_callbacks, this.value_or_error);
this._catch_callbacks = [];
} else if (this.status == this.REJECTED) {
this._then_callbacks = [];
this._flush(this._catch_callbacks, this.value_or_error);
}
return next_promise;
}
catch(method) {
this.then(undefined, method);
}
}
@kaustubh-karkare
Copy link
Author

var delayed_double = function(result) {
  console.info(result);
  return new Promise2(resolve => setTimeout(() => resolve(result * 2), 1000));
};
new Promise2(resolve => setTimeout(() => resolve(1), 1000))
  .then(delayed_double) // 1
  .then(delayed_double) // 2
  .then(delayed_double); // 4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment