Implementing Promises in JavaScript: Specification, Code Walkthrough, and Interview Guide
This article explains the evolution of JavaScript asynchronous programming, details the Promise/A+ specification, provides step‑by‑step custom Promise implementations with full code examples, covers additional Promise methods, and offers interview questions and best‑practice tips for frontend developers.
Introduction
JavaScript asynchronous programming has gone through four stages—Callback, Promise, Generator, and Async/Await. The article begins with a brief history and explains why Promise became the core abstraction for handling async operations.
Promise/A+ Specification
The Promise/A+ spec is broken into terminology, requirements, and cautions. The article highlights three key requirements: three states (pending, fulfilled/resolved, rejected), immutable state transitions, and the then method returning a new promise.
1. Promise has three states: pending , fulfilled (called resolved in the article), and rejected . 2. State can only change from pending to resolved or rejected . 3. Once a state is set it cannot change again.
Step‑by‑Step Implementation
A minimal class is introduced that stores status and data , defines resolve and reject functions, and executes the executor safely.
class Promise {
status = 'pending';
data = '';
constructor(executor) {
function resolve(value) { this.status = 'resolved'; this.data = value; }
function reject(reason) { this.status = 'rejected'; this.data = reason; }
try { executor(resolve, reject); } catch (e) { reject(e); }
}
}The then method is then expanded to handle default callbacks, asynchronous execution via setTimeout , and storage of callbacks when the promise is still pending.
then(onResolved, onRejected) {
onResolved = typeof onResolved === 'function' ? onResolved : v => v;
onRejected = typeof onRejected === 'function' ? onRejected : e => { throw e; };
let promise2 = new Promise((resolve, reject) => {
if (this.status === 'resolved') {
setTimeout(() => {
try { const x = onResolved(this.data); this.resolvePromise(promise2, x, resolve, reject); }
catch (e) { reject(e); }
}, 0);
}
// similar handling for 'rejected' and 'pending' cases …
});
return promise2;
}The crucial resolvePromise helper follows the full Promise/A+ algorithm, handling self‑resolution, thenables, and error propagation.
resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) return reject(new TypeError('Chaining cycle detected'));
if (x instanceof Promise) {
if (x.status === 'pending') x.then(y => this.resolvePromise(promise2, y, resolve, reject), reject);
else x.then(resolve, reject);
return;
}
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
let called = false;
try {
const then = x.then;
if (typeof then === 'function') {
then.call(x, y => { if (called) return; called = true; this.resolvePromise(promise2, y, resolve, reject); },
r => { if (called) return; called = true; reject(r); });
} else { if (called) return; called = true; resolve(x); }
} catch (e) { if (called) return; called = true; reject(e); }
} else {
resolve(x);
}
}Additional Promise Methods
Implementations for catch , finally , done , Promise.all , Promise.race , Promise.resolve , and Promise.reject are provided, each built on top of the core then logic.
catch(onRejected) { return this.then(null, onRejected); }
finally(fn) { return this.then(v => { fn(); return v; }, r => { fn(); throw r; }); }
static all(list) { return new Promise((resolve, reject) => { const results = []; let count = 0; list.forEach((p, i) => p.then(v => { results[i] = v; if (++count === list.length) resolve(results); }, reject)); }); }Interview Guide
The article concludes with a set of common interview questions about Promise fundamentals, implementation details, event‑loop ordering, static methods, drawbacks, sequencing techniques, chain cancellation, error handling, and best practices, giving candidates concrete answers and code snippets.
Conclusion
By walking through the spec, implementing a fully‑featured Promise class, and summarising interview‑level knowledge, the article equips frontend developers with both practical coding skills and deeper conceptual understanding of asynchronous JavaScript.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.