Javascript Promise
JavaScript promises are a powerful tool for writing asynchronous code. They provide a way to handle asynchronous results in a synchronous-like manner, making it easier to reason about and work with asynchronous code.
Promises are objects that represent the eventual result of an asynchronous operation. They have a then
method, which allows you to specify a callback to be executed when the asynchronous operation completes, as well as a catch
method, which allows you to specify a callback to be executed if the asynchronous operation fails.
Here's an example of how you might use a promise to load some data from a server:
function loadData() {
return new Promise((resolve, reject) => {
// make an HTTP request to load the data
const xhr = new XMLHttpRequest();
xhr.open('GET', '/data');
xhr.onload = () => {
if (xhr.status === 200) {
// if the HTTP request is successful, resolve the promise with the response data
resolve(xhr.response);
} else {
// if the HTTP request is not successful, reject the promise with an error message
reject(new Error(`Unable to load data: ${xhr.statusText}`));
}
};
xhr.onerror = () => {
// if there is a network error, reject the promise with an error message
reject(new Error('Network error'));
};
xhr.send();
});
}
// use the promise
loadData()
.then(data => {
// do something with the data
console.log(data);
})
.catch(error => {
// handle any errors
console.error(error.message);
});
Promises also have a finally
method, which allows you to specify a callback to be executed whether the promise is resolved or rejected. This is useful for cleaning up resources or performing other tasks that should be done regardless of the outcome of the asynchronous operation.
Promises can also be composed using methods such as Promise.all
and Promise.race
. Promise.all
allows you to wait for an array of promises to all be resolved, while Promise.race
allows you to specify a callback to be executed as soon as one of the promises in an array is resolved or rejected.
Chaining promises
One of the most powerful features of promises is the ability to chain them together. This allows you to build up a sequence of asynchronous operations, with each operation being executed only after the previous one has completed.
Here's an example of chaining promises:
loadData()
.then(data => {
// do something with the data
return transformData(data);
})
.then(transformedData => {
// do something with the transformed data
return storeData(transformedData);
})
.then(() => {
console.log('All operations completed successfully');
})
.catch(error => {
// handle any errors
console.error(error.message);
});
In this example, the transformData
and storeData
functions both return promises, and the then
method is used to specify a callback to be executed when each promise is resolved. If any of the promises are rejected, the error will be caught by the catch
method at the end of the chain.
Handling multiple asynchronous operations concurrently
In some cases, you may want to perform multiple asynchronous operations concurrently, rather than waiting for each one to complete in sequence. You can use the Promise.all
method to do this.
Here's an example of using Promise.all
:
Promise.all([loadData(), loadMoreData()])
.then(([data, moreData]) => {
// do something with the data and moreData
})
.catch(error => {
// handle any errors
console.error(error.message);
});
In this example, the loadData
and loadMoreData
functions both return promises, and Promise.all
is used to wait for both of them to be resolved. If either of the promises are rejected, the error will be caught by the catch
method.
Using async/await
JavaScript also has a new way of writing asynchronous code called async/await
. This syntax allows you to write asynchronous code in a synchronous-like style, using the async
keyword to define an asynchronous function and the await
keyword to wait for a promise to be resolved.
Here's an example of using async/await
with promises:
async function loadAndTransformData() {
try {
const data = await loadData();
const transformedData = await transformData(data);
return transformedData;
} catch (error) {
// handle any errors
console.error(error.message);
}
}
loadAndTransformData().then(transformedData => {
// do something with the transformed data
});
In this example, the loadAndTransformData
function is marked as async
, which means it returns a promise. The await
keyword is used to wait for the loadData
and transformData
promises to be resolved. If either of these promises is rejected, the error will be caught by the catch
block.