javascript
examples
examples.js⚡javascript
/**
* ========================================
* 9.2 PROMISES - CODE EXAMPLES
* ========================================
*/
/**
* EXAMPLE 1: Creating a Promise
* Basic promise construction
*/
console.log('--- Example 1: Creating a Promise ---');
const simplePromise = new Promise((resolve, reject) => {
const success = true;
setTimeout(() => {
if (success) {
resolve('Operation successful!');
} else {
reject(new Error('Operation failed!'));
}
}, 100);
});
simplePromise
.then((result) => console.log('Result:', result))
.catch((error) => console.error('Error:', error.message));
/**
* EXAMPLE 2: Promise States
* Demonstrating pending, fulfilled, rejected
*/
console.log('\n--- Example 2: Promise States ---');
// Pending promise
const pendingPromise = new Promise(() => {
// Never resolves or rejects
});
console.log('Pending promise:', pendingPromise);
// Immediately fulfilled
const fulfilledPromise = Promise.resolve('Immediate value');
console.log('Fulfilled promise:', fulfilledPromise);
// Immediately rejected
const rejectedPromise = Promise.reject(new Error('Immediate error'));
rejectedPromise.catch(() => {}); // Handle to avoid unhandled rejection
console.log('Rejected promise:', rejectedPromise);
/**
* EXAMPLE 3: .then() Chaining
* Values flow through the chain
*/
console.log('\n--- Example 3: .then() Chaining ---');
Promise.resolve(5)
.then((x) => {
console.log('Step 1:', x);
return x * 2;
})
.then((x) => {
console.log('Step 2:', x);
return x + 3;
})
.then((x) => {
console.log('Step 3:', x);
return x.toString();
})
.then((x) => {
console.log('Final:', x, '(type:', typeof x + ')');
});
/**
* EXAMPLE 4: Returning Promises in Chain
* Async operations in sequence
*/
console.log('\n--- Example 4: Returning Promises ---');
function delay(ms, value) {
return new Promise((resolve) => {
setTimeout(() => resolve(value), ms);
});
}
delay(50, 'First')
.then((result) => {
console.log(result);
return delay(50, 'Second');
})
.then((result) => {
console.log(result);
return delay(50, 'Third');
})
.then((result) => {
console.log(result);
});
/**
* EXAMPLE 5: Error Handling with .catch()
*/
console.log('\n--- Example 5: Error Handling ---');
Promise.resolve('start')
.then((value) => {
console.log(value);
throw new Error('Something went wrong!');
})
.then(() => {
console.log('This will not run');
})
.catch((error) => {
console.log('Caught error:', error.message);
return 'recovered'; // Continue the chain
})
.then((value) => {
console.log('Continued with:', value);
});
/**
* EXAMPLE 6: .finally() Method
* Cleanup that always runs
*/
console.log('\n--- Example 6: .finally() ---');
function fetchData(shouldFail) {
console.log('Loading...');
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldFail) {
reject(new Error('Network error'));
} else {
resolve({ data: 'Success!' });
}
}, 100);
});
}
fetchData(false)
.then((data) => console.log('Data:', data))
.catch((error) => console.error('Error:', error.message))
.finally(() => console.log('Loading complete.'));
/**
* EXAMPLE 7: Promise.all()
* Wait for multiple promises
*/
console.log('\n--- Example 7: Promise.all() ---');
const promise1 = delay(100, 'Result 1');
const promise2 = delay(50, 'Result 2');
const promise3 = delay(75, 'Result 3');
Promise.all([promise1, promise2, promise3]).then((results) => {
console.log('All results:', results);
// Results are in order of input array, not completion order
});
/**
* EXAMPLE 8: Promise.all() Failure
* Fails fast if any promise rejects
*/
console.log('\n--- Example 8: Promise.all() Failure ---');
const successPromise = delay(100, 'Success');
const failPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Failed!')), 50);
});
Promise.all([successPromise, failPromise])
.then((results) => console.log('Results:', results))
.catch((error) => console.log('Promise.all failed:', error.message));
/**
* EXAMPLE 9: Promise.allSettled()
* Wait for all, regardless of outcome
*/
console.log('\n--- Example 9: Promise.allSettled() ---');
const mixedPromises = [
Promise.resolve('Success 1'),
Promise.reject(new Error('Failure')),
Promise.resolve('Success 2'),
];
Promise.allSettled(mixedPromises).then((results) => {
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Promise ${index + 1}: fulfilled with "${result.value}"`);
} else {
console.log(
`Promise ${index + 1}: rejected with "${result.reason.message}"`
);
}
});
});
/**
* EXAMPLE 10: Promise.race()
* First promise to settle wins
*/
console.log('\n--- Example 10: Promise.race() ---');
const slow = delay(200, 'Slow');
const fast = delay(50, 'Fast');
const medium = delay(100, 'Medium');
Promise.race([slow, fast, medium]).then((winner) => {
console.log('Race winner:', winner);
});
/**
* EXAMPLE 11: Promise.any()
* First fulfilled promise wins
*/
console.log('\n--- Example 11: Promise.any() ---');
const rejected1 = Promise.reject(new Error('Error 1'));
const rejected2 = Promise.reject(new Error('Error 2'));
const resolvedLater = delay(100, 'Finally resolved!');
Promise.any([rejected1, rejected2, resolvedLater])
.then((result) => console.log('Any result:', result))
.catch((error) => console.log('All rejected:', error));
/**
* EXAMPLE 12: Timeout Pattern
* Race between operation and timeout
*/
console.log('\n--- Example 12: Timeout Pattern ---');
function timeout(ms) {
return new Promise((_, reject) => {
setTimeout(() => reject(new Error(`Timeout after ${ms}ms`)), ms);
});
}
function fetchWithTimeout(ms) {
const fetchPromise = delay(150, 'Data fetched!');
return Promise.race([fetchPromise, timeout(ms)]);
}
// This will succeed (100ms fetch, 200ms timeout)
fetchWithTimeout(200)
.then((result) => console.log('Fast enough:', result))
.catch((error) => console.log('Too slow:', error.message));
// This will timeout (100ms fetch, 50ms timeout)
fetchWithTimeout(50)
.then((result) => console.log('Fast enough:', result))
.catch((error) => console.log('Too slow:', error.message));
/**
* EXAMPLE 13: Sequential vs Parallel
*/
console.log('\n--- Example 13: Sequential vs Parallel ---');
const tasks = [
() => delay(50, 'Task 1'),
() => delay(50, 'Task 2'),
() => delay(50, 'Task 3'),
];
// Sequential - 150ms total
async function runSequential() {
const start = Date.now();
const results = [];
for (const task of tasks) {
results.push(await task());
}
console.log(`Sequential: ${Date.now() - start}ms`, results);
}
// Parallel - 50ms total
async function runParallel() {
const start = Date.now();
const results = await Promise.all(tasks.map((t) => t()));
console.log(`Parallel: ${Date.now() - start}ms`, results);
}
runSequential();
runParallel();
/**
* EXAMPLE 14: Converting Callback to Promise
*/
console.log('\n--- Example 14: Callback to Promise ---');
// Callback-based function
function fetchDataCallback(id, callback) {
setTimeout(() => {
if (id < 0) {
callback(new Error('Invalid ID'), null);
} else {
callback(null, { id, name: `User ${id}` });
}
}, 50);
}
// Promise wrapper
function fetchDataPromise(id) {
return new Promise((resolve, reject) => {
fetchDataCallback(id, (error, data) => {
if (error) reject(error);
else resolve(data);
});
});
}
// Generic promisify utility
function promisify(fn) {
return function (...args) {
return new Promise((resolve, reject) => {
fn(...args, (error, result) => {
if (error) reject(error);
else resolve(result);
});
});
};
}
const fetchPromisified = promisify(fetchDataCallback);
fetchPromisified(1).then((data) => console.log('Promisified:', data));
/**
* EXAMPLE 15: Retry Pattern
*/
console.log('\n--- Example 15: Retry Pattern ---');
let attemptCount = 0;
function unreliableOperation() {
return new Promise((resolve, reject) => {
attemptCount++;
console.log(`Attempt ${attemptCount}`);
if (attemptCount < 3) {
reject(new Error('Temporary failure'));
} else {
resolve('Success on attempt ' + attemptCount);
}
});
}
function retry(fn, attempts, delayMs) {
return fn().catch((error) => {
if (attempts <= 1) {
throw error;
}
return delay(delayMs, null).then(() => retry(fn, attempts - 1, delayMs));
});
}
retry(unreliableOperation, 5, 100)
.then((result) => console.log('Retry result:', result))
.catch((error) => console.log('All retries failed:', error.message));
/**
* EXAMPLE 16: Promise Memoization
*/
console.log('\n--- Example 16: Memoization ---');
function memoize(fn) {
const cache = new Map();
return function (key) {
if (cache.has(key)) {
console.log('Cache hit for:', key);
return cache.get(key);
}
console.log('Cache miss for:', key);
const promise = fn(key);
cache.set(key, promise);
return promise;
};
}
const fetchUser = memoize((id) => {
return new Promise((resolve) => {
setTimeout(() => resolve({ id, name: `User ${id}` }), 100);
});
});
// First call - cache miss
fetchUser(1).then((user) => console.log('First:', user));
// Second call - cache hit
fetchUser(1).then((user) => console.log('Second:', user));
// Different key - cache miss
fetchUser(2).then((user) => console.log('Third:', user));
/**
* EXAMPLE 17: Promise Queue
* Process items with concurrency limit
*/
console.log('\n--- Example 17: Concurrency Limit ---');
class PromiseQueue {
constructor(concurrency = 1) {
this.concurrency = concurrency;
this.running = 0;
this.queue = [];
}
add(promiseFactory) {
return new Promise((resolve, reject) => {
this.queue.push({
factory: promiseFactory,
resolve,
reject,
});
this.process();
});
}
process() {
while (this.running < this.concurrency && this.queue.length > 0) {
const { factory, resolve, reject } = this.queue.shift();
this.running++;
factory()
.then(resolve)
.catch(reject)
.finally(() => {
this.running--;
this.process();
});
}
}
}
const queue = new PromiseQueue(2);
for (let i = 1; i <= 5; i++) {
queue
.add(() => {
console.log(`Task ${i} started`);
return delay(100, `Task ${i} result`);
})
.then((result) => console.log(`Task ${i} done:`, result));
}
/**
* EXAMPLE 18: Promise.withResolvers()
* New way to create promises (ES2024)
*/
console.log('\n--- Example 18: Deferred Pattern ---');
// Manual deferred pattern (before Promise.withResolvers)
function createDeferred() {
let resolve, reject;
const promise = new Promise((res, rej) => {
resolve = res;
reject = rej;
});
return { promise, resolve, reject };
}
const deferred = createDeferred();
// Resolve later
setTimeout(() => {
deferred.resolve('Deferred value!');
}, 100);
deferred.promise.then((value) => console.log('Deferred:', value));
/**
* EXAMPLE 19: Error Recovery
*/
console.log('\n--- Example 19: Error Recovery ---');
function fetchWithFallback(primary, fallback) {
return primary.catch((error) => {
console.log(`Primary failed: ${error.message}, trying fallback`);
return fallback;
});
}
const primaryServer = Promise.reject(new Error('Primary down'));
const fallbackServer = Promise.resolve('Fallback data');
fetchWithFallback(primaryServer, fallbackServer).then((data) =>
console.log('Got:', data)
);
/**
* EXAMPLE 20: Real-World Example - API Client
*/
console.log('\n--- Example 20: API Client ---');
class APIClient {
constructor(baseURL) {
this.baseURL = baseURL;
this.cache = new Map();
}
// Simulated fetch
fetch(endpoint, options = {}) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (endpoint.includes('error')) {
reject(new Error(`Failed to fetch ${endpoint}`));
} else {
resolve({
endpoint,
data: { message: 'Success' },
timestamp: Date.now(),
});
}
}, 100);
});
}
get(endpoint, { cache = false, timeout = 5000 } = {}) {
const cacheKey = `GET:${endpoint}`;
if (cache && this.cache.has(cacheKey)) {
return Promise.resolve(this.cache.get(cacheKey));
}
const fetchPromise = this.fetch(endpoint);
const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => reject(new Error('Request timeout')), timeout);
});
return Promise.race([fetchPromise, timeoutPromise]).then((response) => {
if (cache) {
this.cache.set(cacheKey, response);
}
return response;
});
}
getMultiple(endpoints) {
return Promise.allSettled(endpoints.map((e) => this.get(e)));
}
}
const api = new APIClient('https://api.example.com');
// Single request
api.get('/users').then((response) => console.log('Single:', response.endpoint));
// Multiple requests
api.getMultiple(['/users', '/posts', '/error-endpoint']).then((results) => {
console.log(
'Multiple:',
results.map((r) =>
r.status === 'fulfilled' ? r.value.endpoint : r.reason.message
)
);
});
console.log('\n========================================');
console.log('End of Promise Examples');
console.log('========================================');