Login to disable ads
Login now and become premium user

Promises in JavaScript: Concepts, Implementation, and Interview Preparation

By-Shadab Ali

Explore the intricate world of JavaScript promises with our comprehensive guide. Learn the fundamental concepts, delve into practical implementation techniques, and prepare for interviews with expert insights. Master promises in JavaScript and enhance your coding skills today!


Definition

  1. Promises in JavaScript are a programming pattern used to handle asynchronous operations. They allow you to write code that can execute asynchronously and provide a way to handle success or failure of that asynchronous operation.

  2. A promise is an object that represents the eventual completion (or failure) of an asynchronous operation, and provides a way to register callbacks to be executed when the operation completes.

  3. A promise has three states:

  • Pending: The initial state, before the promise has resolved or rejected.
  • Fulfilled: The state of a promise when it has successfully completed. This is also known as "resolved."
  • Rejected: The state of a promise when it has failed to complete. This is also known as "rejected."

How to create promise

Promises are created using the Promise constructor, which takes a function called an executor as its argument. The executor function takes two arguments: a resolve function and a reject function. When the asynchronous operation is complete, you call one of these functions to resolve or reject the promise.

const promise = new Promise((resolve, reject) => {
  // Perform some asynchronous operation
  // When it's done, call resolve() with the result
  // or reject() with an error if something went wrong.
});

The new Promise constructor is invoked, and the executor function is executed synchronously

Once a promise is created, you can attach callbacks to it using the then() and catch() methods. The then() method takes a callback that will be executed if the promise is fulfilled, and the catch() method takes a callback that will be executed if the promise is rejected.

promise
  .then((result) => {
    // Do something with the result
  })
  .catch((error) => {
    // Handle the error
  });
Im a caption

You can also chain multiple then() methods together to create a sequence of asynchronous operations. Each then() method takes a callback that returns a new promise. If the callback returns a value, the new promise is fulfilled with that value. If the callback throws an error or returns a rejected promise, the new promise is rejected with that error.

Before Promises

Before the introduction of Promises in JavaScript, the primary mechanism for handling asynchronous operations was through traditional callback functions. Callbacks were used to specify what should happen when an asynchronous operation completed or encountered an error.

problems with this approach

  1. Callback hell- Asynchronous code that involved multiple nested callbacks could quickly become difficult to read and maintain. This nesting structure, often referred to as "callback hell" or "pyramid of doom," made code hard to understand, debug, and reason about

  2. Error Handling- Error handling in callback-based code could be cumbersome. Errors often had to be passed as parameters to the callbacks, and it was the responsibility of each callback to handle errors appropriately. This approach made it challenging to centralize error handling and propagate errors across the codebase.

  3. Lack of structure- Without a standardized mechanism for handling asynchronous operations, developers had to rely on individual coding patterns and conventions. This lack of structure led to inconsistency and made it harder to share and reuse asynchronous code.

  4. inversion of control- -it not actually a problem. it is good design pattern with callback may create a problem -giving control to different part of code -less reuseable

Mcq Based output question

Question 1
console.log("start");
const promise1 = new Promise((resolve, reject) => {
  console.log(1);
});
console.log("end");
Question 2
console.log("start");
const promise1 = new Promise((resolve, reject) => {
  console.log(1);
  resolve(2);
});
promise1.then((res) => {
  console.log(res);
});
console.log("end");
Question 3
console.log("start");
const promise1 = new Promise((resolve, reject) => {
  console.log(1);
  resolve(2);
  console.log(3);
});
promise1.then((res) => {
  console.log(res);
});
console.log("end");
Question 4
console.log("start");
const promise1 = new Promise((resolve, reject) => {
  console.log(1);
});
promise1.then((res) => {
  console.log(2);
});
console.log("end");
Question 5
console.log("start");
const fn = () =>
  new Promise((resolve, reject) => {
    console.log(1);
    resolve("success");
  });
console.log("middle");
fn().then((res) => {
  console.log(res);
});
 
console.log("end");
Question 6
console.log("start");
setTimeout(() => {
  console.log("setTimeout");
});
Promise.resolve().then(() => {
  console.log("resolve");
});
console.log("end");
Question 7
const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});
promise.then((res) => {
  console.log(res);
});
console.log(4);
Question 8
console.log("start");
 
const promise1 = Promise.resolve().then(() => {
  console.log("promise1");
  const timer2 = setTimeout(() => {
    console.log("timer2");
  }, 0);
});
 
const timer1 = setTimeout(() => {
  console.log("timer1");
 
  const promise2 = Promise.resolve().then(() => {
    console.log("promise2");
  });
}, 0);
 
console.log("end");
Question 9
let p = new Promise((resolve, rejected) => {
  setTimeout(() => {
    rejected("200");
  }, 2000);
});
 
p.then(
  (res) => {
    console.log("res", res);
  },
  (err) => {
    console.log("err", err);
  }
);
Question 10
let p = new Promise((resolve, rejected) => {
  setTimeout(() => {
    resolve("200");
  }, 2000);
});
 
p.then(
  (res) => {
    console.log("res", res);
  },
  (err) => {
    console.log("err", err);
  }
);
Question 11
// This doesn't make sense w/ promises:
console.log(Promise.resolve(42));
 
// We must use the `.then` interface:
Promise.resolve(42).then((value) => console.log(value));

Answer promise object The answer 42

Question 12
function job(state) {
  return new Promise(function (resolve, reject) {
    if (state) {
      resolve("success");
    } else {
      reject("error");
    }
  });
}
 
let promise = job(true);
 
promise
  .then(function (data) {
    console.log(data);
    return job(false);
  })
  .catch(function (error) {
    console.log(error);
    return "Error caught";
  })
  .then(function (data) {
    console.log(data);
    return job(true);
  })
  .catch(function (error) {
    console.log(error);
  });
 
// 1. error, success, Error caught
// 2. success, success
// 3. success, error, success, error
// 4. success, error, Error caught
// 5. error, Error caught, success
// 6. error, Error caught, success, error
// 7. success, error, error
// 8. success, success, success
Answer
  1. success, error, Error caught
Question 13
function job() {
  return new Promise(function (resolve, reject) {
    reject();
  });
}
 
let promise = job();
promise
  .then(function () {
    console.log("Success 1");
  })
  .then(function () {
    console.log("Success 2");
  })
  .then(function () {
    console.log("Success 3");
  })
  .catch(function () {
    console.log("Error 1");
  })
  .then(function () {
    console.log("Success 4");
  });
 
// 1. Error 1
// 2. Success 1, Error 1
// 3. Success 1, Success 2, Success 3, Success 4
// 4. Success 1, Success 2, Success 3, Error 1, Success 4
// 5. Error 1, Success 1, Success 2, Success 3, Succes 4
// 6. Error 1, Success 4
Answer
Error 1, Success 4
Question 14
    var p = new Promise((resolve, reject) => {
    reject(Error('The Fails!'))
    })
    p.catch(error => console.log(error.message))
    p.catch(error => console.log(error.message))
 
    // output
    A. print message once
    B. print message twice
    C. UnhandledPromiseRejectionWarning
    D. process exits
Answer

B. print message twice

Question 15
 
    var p = new Promise((resolve, reject) => {
    return Promise.reject(Error('The Fails!'))
    })
    p.catch(error => console.log(error.message))
    p.catch(error => console.log(error.message))
    // output
    A. print message once
    B. print message twice
    C. UnhandledPromiseRejectionWarning
    D. process exits

Answer C. UnhandledPromiseRejectionWarning

Question 16
    var p = new Promise((resolve, reject) => {
        reject(Error('The Fails!'))
    })
    .catch(error => console.log(error))
    .then(error => console.log(error))
    // output
    A. print error and `undefined`
    B. print error twice
    C. UnhandledPromiseRejectionWarning
    D. undefined

Answer A. print error and undefined

Question 17
    Promise.resolve('Success!')
    .then(data => {
        data.toUpperCase()
    })
    .then(data => {
        console.log(data)
    })
    // output
    A. print "SUCCESS!"
    B. print "Success!"
    C. print "SUCCESS!" and "SUCCESS!"
    D. prints `undefined`

Answer D. prints undefined

Question 18
    var p = new Promise((resolve, reject) => {
    reject(Error('The Fails!'))
    })
    .catch(error => console.log(error.message))
    .catch(error => console.log(error.message))
    // output
    A. print error message once
    B. print error message twice
    C. UnhandledPromiseRejectionWarning
    D. process exits

Answer A. print error message once

Question 19
    new Promise((resolve, reject) => {
    resolve('Success!')
    })
    .then(() => {
        throw Error('Oh noes!')
    })
    .catch(error => {
        return "actually, that worked"
    })
    .catch(error => console.log(error.message))
    // output
    A. print message once
    B. print error message twice
    C. UnhandledPromiseRejectionWarning
    D. nothing prints

Answer D. nothing prints

Question to answer after understating promise

  • What is a Promise in JavaScript?
  • Explain the three states of a Promise.
  • How do you create a Promise in JavaScript?
  • How do you handle the fulfillment and rejection of a Promise?
  • What are the differences between using Promises and traditional callback functions for handling asynchronous operations?
  • How do you chain Promises together?
  • How do you handle errors in a Promise chain?
  • What is the purpose of the .catch() method in a Promise chain?
  • Explain the difference between Promise.all() and Promise.race().
  • How do you convert callback-based functions into Promise-based functions?
  • What are some common anti-patterns or pitfalls to avoid when working with Promises?
  • How does async/await syntax relate to Promises? How do you use async/await with Promises?
  • How would you handle multiple Promises in parallel?
  • Explain how to implement a timeout for a Promise.
  • What are the advantages of using Promises over callbacks?
  • How do you handle asynchronous code that relies on multiple Promises and requires them to be executed in a specific order?
  • How do you handle situations where you need to limit the concurrency of multiple asynchronous operations using Promises?
  • How do you handle cancellation of a Promise-based asynchronous operation?
  • How do you handle retries for a Promise-based asynchronous operation that may fail?
  • How do you handle long-running Promises to prevent them from blocking the main JavaScript thread?
  • How do you handle the situation when you have a mix of Promises and non-Promise asynchronous operations and need to ensure they are all completed before proceeding?
  • How do you handle timeouts for Promises, ensuring that they don't exceed a certain duration?
  • How do you handle multiple Promises in parallel and wait for all of them to resolve?
  • How do you handle multiple Promises in parallel and wait for the first one to resolve?
  • How do you handle multiple Promises in parallel and wait for at least a certain number of them to resolve?
  • How do you handle multiple Promises in parallel and wait for the first one to reject?
  • How do you handle multiple Promises in parallel and wait for at least one of them to reject?
  • How do you handle the situation when you need to pass data between Promises in a chain?
  • How do you handle the situation when you need to perform cleanup actions after a Promise chain completes, regardless of whether it resolved or rejected?
  • How do you handle the situation when you want to create a custom Promise that wraps a callback-based asynchronous operation?
  • How do you handle the situation when you want to create a Promise that resolves or rejects after a specific delay?
  • How do you handle the situation when you want to create a Promise that resolves immediately with a specific value?
  • How do you implement a custom Promise-like object from scratch, without using the built-in Promise constructor?
  • How do you handle circular dependencies or interdependent Promises in a complex asynchronous scenario?
  • How do you handle memory leaks when working with Promises that are not properly cleaned up?
  • How do you handle race conditions or synchronization issues when multiple Promises are updating shared data?
  • How do you handle complex error handling scenarios, such as retrying with exponential backoff and error propagation in a Promise chain?
  • How do you handle Promises that rely on external resources, such as network requests, and need to implement timeouts, retries, and cancellation?
  • How do you handle Promises in a multi-threaded environment, such as a web worker or Node.js cluster?
  • How do you optimize performance and reduce unnecessary Promise overhead in high-throughput applications?
  • How do you handle Promise composition and nesting when dealing with complex data transformations and dependencies?
  • How do you handle the situation when you need to extend or subclass the built-in Promise object to add custom behavior?
  • Implement a function retryWithDelay that takes a function asyncOperation and a maximum number of retries maxRetries. The asyncOperation is an asynchronous function that returns a Promise. The retryWithDelay function should attempt to execute the asyncOperation up to maxRetries times, with an increasing delay between each retry. If the operation fails after all retries, the function should reject with the last error encountered. Implement the retryWithDelay function using Promises and demonstrate its usage with an example.