Skip to content

Instantly share code, notes, and snippets.

@Nitive
Last active July 5, 2022 14:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Nitive/8cba3b5c19620ec7dc996e1f109103cb to your computer and use it in GitHub Desktop.
Save Nitive/8cba3b5c19620ec7dc996e1f109103cb to your computer and use it in GitHub Desktop.
JavaScript Promise implementation
function addHandler(fn, arg, resolve, reject) {
try {
const result = fn(arg);
if (result instanceof MyPromise) {
result.then(resolve).catch(reject);
} else {
process.nextTick(() => resolve(result));
}
} catch (err) {
process.nextTick(() => reject(err));
}
}
class MyPromise {
#status = "started";
#thenFn = null;
#catchFn = null;
static resolve(arg) {
return new MyPromise((resolve) => {
process.nextTick(() => resolve(arg));
});
}
static reject(err) {
return new MyPromise((_resolve, reject) => {
process.nextTick(() => reject(err));
});
}
constructor(fn) {
fn(this.#resolve, this.#reject);
}
#resolve = (arg) => {
if (this.#status === "started") {
this.#status = "resolved";
this.#thenFn?.(arg);
}
};
#reject = (arg) => {
if (this.#status === "started") {
this.#status = "rejected";
if (!this.#catchFn) {
console.warn("Unhandled promise rejection");
}
this.#catchFn?.(arg);
}
};
then(fn) {
return new MyPromise((resolve, reject) => {
this.#thenFn = (arg) => {
addHandler(fn, arg, resolve, reject);
};
this.#catchFn = reject;
});
}
catch(fn) {
return new MyPromise((resolve, reject) => {
this.#catchFn = (arg) => {
addHandler(fn, arg, resolve, reject);
};
this.#thenFn = resolve;
});
}
}
// Tests
new MyPromise((resolve) => setTimeout(() => resolve(), 1000))
.then(() => {
console.log(1);
})
.then(() => {
console.log(2);
throw new Error("Error 3");
})
.catch((err) => {
console.log(3);
console.log(err);
})
.then(() => {
console.log(4);
return MyPromise.resolve(5);
})
.then((arg) => {
console.log(arg);
return new MyPromise((resolve) => setTimeout(() => resolve(6), 100));
})
.then((arg) => {
console.log(arg);
return new MyPromise((_resolve, reject) => setTimeout(() => reject(7), 100));
})
.catch((err) => {
console.log(err);
return MyPromise.reject(8);
})
.catch((err) => {
console.log(err);
})
.then(() => {
console.log("fin");
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment