Javascript is an asynchronous programming language. the main reason why its asynchronous because it is also single threaded.
you can use Webworkers to utilise more then one threads at a time.
What is asynchronous Programming:
In programming, the term asynchronous refers to code that doesn't block the main program flow while waiting for long-running operations to complete. This is in contrast to synchronous code, which executes line by line and waits for each operation to finish before moving on.
Why do we need it:
Suppose we're making an api call to the server which takes 5 second of time, now instead of waiting for 5 seconds we can do some other computations like showing
In programming languages like javascript which is single treaded it means it can only utilise one thread at ones, so you would have to wait for code to execute line by line, which can increase wait time since we can only run one process at a time.
That's why javascript is Asynchronous
Let's understand promises and how to implement them in javascript, we will talk about how we use promises and async/await to do our asynchronous operations.
Promises
Has someone ever made a promise to you?
Promises in JavaScript are similar to that. When a promise is made, it represents a value that may be available now, in the future, or never.
A promise in JavaScript can be in one of three states:
- Pending: Initial state, neither fulfilled nor rejected.
- Fulfilled: The operation completed successfully.
- Rejected: The operation failed.
Here's an example of a promise:
let promise = new Promise((resolve, reject) => {
// Simulate an asynchronous operation using setTimeout
setTimeout(() => {
let result = true; // Simulating result positive value
if (result) {
resolve("Promise fulfilled!");
} else {
reject("Promise rejected!");
}
}, 1000);
});
promise
.then((message) => {
console.log(message); // Logs "Promise fulfilled!" if the promise is resolved
})
.catch((error) => {
console.log(error); // Logs "Promise rejected!" if the promise is rejected
});
Here is a simple breakdown of above code:
1. Creating a Promise:
let promise = new Promise((resolve, reject) => {...});
- This line creates a new Promise object named
promise
. - The
Promise
constructor takes an executor function with two arguments:resolve
andreject
.
- This line creates a new Promise object named
2. Simulating Asynchronous Operation:
setTimeout(() => {...}, 1000);
- Inside the executor function, a
setTimeout
function is used to simulate an asynchronous operation (suppose we are making an api call and it is taking 1 second) - This function delays the execution of the code inside it for 1 second (1000 milliseconds).
- The anonymous function passed to
setTimeout
will be executed after the delay.
- Inside the executor function, a
3. Resolving or Rejecting the Promise:
let result = true; // Let's assume our api returned positive response like 201
- A variable
result
is declared and assigned a value (here,true
). This simulates the outcome of the asynchronous operation.
- A variable
if (result) { resolve("Promise fulfilled!"); } else { reject("Promise rejected!"); }
- An if-else statement checks the value of
result
.- If
result
is truthy (here,true
), theresolve
function is called with the message "Promise fulfilled!". This indicates successful completion of the asynchronous operation. - If
result
is falsy, thereject
function is called with the message "Promise rejected!". This indicates an error occurred during the operation.
- If
- An if-else statement checks the value of
4. Handling Promise Resolution/Rejection:
promise.then((message) => {...}, .catch((error) => {...});
- After creating the promise, the
.then
and.catch
methods are chained to handle its outcome. .then
takes a callback function that executes if the promise is resolved. Here, it logs the message received throughresolve
("Promise fulfilled!")..catch
takes a callback function that executes if the promise is rejected. Here, it logs the error message received throughreject
("Promise rejected!").
- After creating the promise, the
This is how you do Promises in javascript now let's talk about Async/await
Async await
In javascript async await is just a better way of doing promises, it gives us better syntax and its easier to understand
Let's see the example of promises
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
const data = { name: 'John Doe', age: 30 };
resolve(data); // Simulating successful data fetching
}, 2000);
});
};
const displayData = async () => {
try {
console.log('Fetching data...');
const data = await fetchData(); // Wait for the promise to resolve
console.log('Data:', data);
} catch (error) {
console.error('Error:', error);
}
};
displayData();
Let's break down the above code
1. Asynchronous Function (displayData
):
const displayData = async () => { ... }
- The
async
keyword before the function declaration marksdisplayData
as an asynchronous function. - Asynchronous functions implicitly return a promise.
- The
2. Error Handling (try...catch
):
try { ... } catch (error) { ... }
- A
try...catch
block is used to handle potential errors during the asynchronous operation.- Code within the
try
block is executed. If an error occurs, it's caught by thecatch
block.
- Code within the
- A
3. await
Keyword:
const data = await fetchData();
- The
await
keyword is used inside thetry
block. - It pauses the execution of
displayData
until the promise returned byfetchData()
is either resolved or rejected.
- The
4. Promise Resolution:
- When
fetchData()
's promise resolves (after 2 seconds), the value it resolves with (thedata
object) is assigned to thedata
variable. - Execution continues to the next line (
console.log('Data:', data);
), logging the fetched data.
5. Promise Rejection (If Any):
- If
fetchData()
's promise were to be rejected (e.g., due to a network error), thecatch
block would be executed. - The
error
object would contain information about the rejection, which is then logged to the console.
In essence, async/await
provides a more synchronous-looking way to handle asynchronous operations in JavaScript, making code easier to read and reason about.
Conclusion:
Both Promises and Async/Await are powerful tools for dealing with asynchronous operations in JavaScript. Promises provide a structured way to handle the eventual success or failure of these operations. Async/Await builds upon Promises, offering a more readable and intuitive syntax that resembles synchronous code.
Choose Promises when:
- You need a more fundamental way of working with asynchronous code.
- You're dealing with older browsers that might not fully support Async/Await.
Choose Async/Await when:
- You want a cleaner and more synchronous-like coding style.
- Error handling and sequential asynchronous operations are a priority.
At the end it all depends on your project's needs and your preference as a developer.