Wilf

JavaScript Promises

Monday 24th July 2023 (updated: Monday 1st January 2024)

JavaScript

Research

Development

The whole concept of Promises in JavaScript I have always found useful. The action is handled asynchronously and the result is either a resolution 'resolve' or a rejection 'reject'.
Where it started to mangle with my brain cells is with the async/await functionality introduced in later versions of ECMAScript.

A simple JavaScript Promise can be defined as below:


const myPromise = new Promise((resolve, reject) => {
  // Simulate an asynchronous operation (e.g., fetching data from a server)
  setTimeout(() => {
    const data = { message: 'Promise resolved with data!' };
    // Resolve the Promise with the data
    resolve(data);
    // Alternatively, you can reject the Promise with an error
    // reject(new Error('Something went wrong!'));
  }, 2000); // Simulate a 2-second delay
});

// Consuming the Promise using `then` and `catch` methods
myPromise
  .then((data) => {
    console.log(data.message); // Output: "Promise resolved with data!"
  })
  .catch((error) => {
    console.error(error); // Output: Any error that occurred during the Promise execution
  });

Async / Await can be used to make it all supposedly more readable. Any form of nesting in code does anything but simplify things, for me.

In the following code fetchData() returns a Promise which itself does the work. i.e. returns the data. Or not!


// Function that returns a Promise after a simulated delay
function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      const data = { message: 'Data fetched successfully!' };
      resolve(data);
      // Alternatively, you can reject the Promise with an error
      // reject(new Error('Failed to fetch data!'));
    }, 2000); // Simulate a 2-second delay
  });
}

// Asynchronous function using async/await
async function fetchAsyncData() {
  try {
    // Wait for the Promise to be resolved and get the data
    const data = await fetchData();
    console.log(data.message); // Output: "Data fetched successfully!"
  } catch (error) {
    console.error(error); // Output: Any error that occurred during the Promise execution
  }
}

// Call the asynchronous function
fetchAsyncData();

Prefixing the function fetchAsyncData() establishes the function as being asynchronous.
On the plus side we now have an element of reusability which can only be a good thing. Unless, of course, you never have the requirement to reuse a function. e.g. initialisation of game data. But, it's good to be modern.