DEV Community

Ayako yk
Ayako yk

Posted on

Difference Between Promise And Async

When I had errors with async/await and asked for help, I was told to look up “Promise”. I was like, “Why? It’s about async and I’m not using a promise in code.” And then I found then(), .try(), .catch(), and finally(), which all looked the same to me. I felt that now was the time to learn more about these. So, today I’m going to share what I learned, especially focusing on the basics to get the big picture of a promise.

This article includes these topics, and I hope you’ll get familiar with a promise and its usage.

  1. Synchronous vs Asynchronous
  2. Promise
  3. Async / Await
  4. Error handlings

Synchronous vs Asynchronous
When understanding a promise, we need to know JavaScript. JavaScript is synchronous and single-threaded, meaning only one operation can be processed at a time, and it is processed in the order of the code written. When multiple tasks occur, the browser has to wait for each line of code to finish its task before going on to the next line, and while waiting for it, the browser looks freezing and disables users to even scroll. How do you think JavaScript manages multiple tasks? Yes, Asynchronous. Asynchronous works independently and enables a program to continue running while waiting, and once the task is done it lets your program know the result of the task.

setTimeout(() => { console.log("Hello World")}, 3000);
Enter fullscreen mode Exit fullscreen mode

(While waiting for the message to be displayed in three seconds, we cannot do anything.)

Promise
Here, a promise comes in. A promise keeps observing the task running independently and returns the result with a value if that task is successfully done or it is failed. Now we know why it is called promise. As MDN describes, “instead of immediately returning the final value, the asynchronous method returns a promise to supply the value at some point in the future.”

Here is how to use a promise:

  1. Produce/Instantiate a Promise
const example = new Promise((resolveFunction,rejectFunction) => {
    resolveFunction();   // when successful
    rejectFunction();    // when failed
});
Enter fullscreen mode Exit fullscreen mode
  1. Consume the Promise
example.then(
    (value) => { /* code when successful */ }, 
    (error) => { /* code when failed */ }
)
Enter fullscreen mode Exit fullscreen mode

We write two blocks of code: one for producing/instantiating a promise using the new keyword, and the other for calling the function and actually using it. Do you remember the asynchronous processes task(s) independently running? These multi-tasks include fetching data from API, which might not always be done successfully. So, we need two functions (callback functions) depending on whether it’s a success or not. And they are resolve, when it is successful, and rejected when it’s a failure.

When calling a function (example in this case), we wait until we receive the result before choosing either a resolve function or a reject function. There are three states, pending (we don’t know the result yet), fulfilled (we get the value successfully), and rejected (we get an error message). Once we get the result, then we can move on to the then() part, where either resolve or reject is run. then() method can take up to two callback functions, but these could be optional.

… Isn’t it then( ).catch( )? Yes, this code is also correct. Both work in the same way in some situations and don’t in other cases. If we use then().catch(), we write a resolve function in the then() method and a reject function in the catch() method, which handles an error and I’ll talk about it later.

A Promise was standardized and introduced in ES2015, but it is not syntax but an object, its syntax is complicated, and it is not perfect in handling errors. So, the async function was introduced.

Async / Await
Async/await is built on promises! An async function always returns a promise instance.

const delayFunction = () => {
    return new Promise(resolve => {
        setTimeout(() => { resolve('Hello World')}, 3000);
    });
}

const example = async () => {
    const result = await delayFunction();
    console.log(result);
}

example();
Enter fullscreen mode Exit fullscreen mode

In the async function, we add the word await before the calling function. This await awaits promise asynchronous until it is resolved or rejected. Now the code is simpler and looks synchronous. It is read from top to bottom, and easy to debug.

Error handlings
Now let’s look at error handlings. When there’s an error, JavaScript normally stops and generates an error message.

with a promise
A promise has then() and catch() methods. So when an error occurs, the catch method is called and an error is thrown.

const example = new Promise((resolve, reject) => {
    resolve();
    reject();
});

// When success
example.then(() => {
    // This callback function is called
}).catch(error => {
    // This callback function is not called
})

// When failure
example.then(() => {
    // This callback function is not called
}).catch(error => {
    console.log(error.message)
})
Enter fullscreen mode Exit fullscreen mode

try…catch handles errors as well. We wrap a block of code to check whether there is an error. If not, the code in the try block is run. If there’s an error, the code in the try block is ignored and the code in the catch block is run, and an error message is thrown.

with async/await

const example = async (url) => {
    try{
        const response = await fetch(url);
        return await response.json();
    } catch(error) {
        console.log(error)
    }
}
Enter fullscreen mode Exit fullscreen mode

Async/await can use try…catch because it works like synchronous. However, a promise cannot use try…catch because it is asynchronous, which means an error can occur outside of the scope. That’s why a promise uses .then().catch() for error handling.

So, here’s a recap.

  1. Synchronous runs in sequence, and asynchronous runs in parallel.
  2. A promise makes it possible for JavaScript to handle asynchronous actions by supplying a value sometime in the future.
  3. Async/Await enables a promise to be written easier and cleaner.
  4. For error handlings, a promise uses catch(), whereas async/await is used with try-catch.

A promise has some more important methods, such as Promise.all and Promise.race, which we should be familiar with to understand async/await better, and there are also then().catch().finally() and try-catch-finally to handle errors. These could be the next step to learning after understanding the basics of a promise. I hope this article could help you understand a promise and async better.

Top comments (0)