JavaScript Promises

Handle asynchronous operations elegantly

🤝 What are Promises?

A Promise is an object representing the eventual completion or failure of an asynchronous operation. It's a cleaner alternative to callbacks.


// Creating a simple promise
const myPromise = new Promise((resolve, reject) => {
    const success = true;
    if (success) {
        resolve('Operation successful!');
    } else {
        reject('Operation failed!');
    }
});

myPromise.then(result => console.log(result));
                                    

Output:

Operation successful!

Promise States

Pending

Initial state, not fulfilled or rejected

const promise = new Promise(() => {
    // Still running...
});

Fulfilled

Operation completed successfully

resolve('Success!');

Rejected

Operation failed

reject('Error occurred!');
🔒

Settled

Either fulfilled or rejected

// Promise is settled
// (no longer pending)

🔹 Creating Promises

Here's how to create and use promises:

// Creating a promise that resolves after 2 seconds
function delay(ms) {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(`Waited for ${ms} milliseconds`);
        }, ms);
    });
}

// Using the promise
delay(2000).then(message => {
    console.log(message);
});

// Promise that might fail
function randomSuccess() {
    return new Promise((resolve, reject) => {
        const random = Math.random();
        if (random > 0.5) {
            resolve('Success! Random number: ' + random);
        } else {
            reject('Failed! Random number: ' + random);
        }
    });
}

Output:

(After 2 seconds...)

Waited for 2000 milliseconds

🔹 Promise Methods

Promises have several useful methods:

const promise = new Promise((resolve, reject) => {
    const success = Math.random() > 0.5;
    setTimeout(() => {
        if (success) {
            resolve('Data loaded successfully');
        } else {
            reject(new Error('Failed to load data'));
        }
    }, 1000);
});

// .then() - handles success
promise.then(data => {
    console.log('Success:', data);
});

// .catch() - handles errors
promise.catch(error => {
    console.log('Error:', error.message);
});

// .finally() - runs regardless of outcome
promise.finally(() => {
    console.log('Promise completed');
});

// Chaining all together
promise
    .then(data => console.log('Success:', data))
    .catch(error => console.log('Error:', error.message))
    .finally(() => console.log('Cleanup completed'));

Output (if successful):

Success: Data loaded successfully

Promise completed

Cleanup completed

🔹 Promise Chaining

Chain multiple promises together:

// Simulating API calls
function fetchUser(id) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve({ id: id, name: 'John Doe' });
        }, 1000);
    });
}

function fetchUserPosts(userId) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(['Post 1', 'Post 2', 'Post 3']);
        }, 1000);
    });
}

function fetchPostComments(post) {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve([`Comment on ${post}`, `Reply to ${post}`]);
        }, 1000);
    });
}

// Chaining promises
fetchUser(123)
    .then(user => {
        console.log('User:', user.name);
        return fetchUserPosts(user.id);
    })
    .then(posts => {
        console.log('Posts:', posts);
        return fetchPostComments(posts[0]);
    })
    .then(comments => {
        console.log('Comments:', comments);
    })
    .catch(error => {
        console.log('Error in chain:', error);
    });

Output:

(After 1 second...) User: John Doe

(After 2 seconds...) Posts: ["Post 1", "Post 2", "Post 3"]

(After 3 seconds...) Comments: ["Comment on Post 1", "Reply to Post 1"]

🔹 Promise.all() and Promise.race()

Handle multiple promises at once:

// Multiple promises
const promise1 = Promise.resolve('First');
const promise2 = Promise.resolve('Second');
const promise3 = Promise.resolve('Third');

// Promise.all() - waits for all to complete
Promise.all([promise1, promise2, promise3])
    .then(results => {
        console.log('All results:', results);
    });

// Promise.race() - returns first completed
Promise.race([
    new Promise(resolve => setTimeout(() => resolve('Fast'), 1000)),
    new Promise(resolve => setTimeout(() => resolve('Slow'), 3000))
])
.then(result => {
    console.log('First result:', result);
});

// Real example: Loading multiple resources
const loadUser = fetch('/api/user');
const loadPosts = fetch('/api/posts');
const loadComments = fetch('/api/comments');

Promise.all([loadUser, loadPosts, loadComments])
    .then(responses => {
        console.log('All data loaded');
        // Process all responses
    })
    .catch(error => {
        console.log('One or more requests failed:', error);
    });

Output:

All results: ["First", "Second", "Third"]

(After 1 second...) First result: Fast

🧠 Test Your Knowledge

What are the three states of a Promise?