Reputation: 2511
I have been using Promises
and async/await
, they are pretty much the same thing right? Usually what I would do is wrap my promise and return it etc.
function someFetchThatTakesTime(){
// Promisify the request.
return new Promise((resolve, reject) => {
if(allGood){
resolve();
}else{
reject();
});
}
Then I can do:
someFetchThatTakesTime()
.then(console.log('all good.')
.catch(console.log('some error occured.');
or I can do the:
async function wrapMyFetch() {
try {
// Make the async call.
data = await someFetchThatTakesTime();
return data;
} catch(err) {
// Propagate the exception up stream.
throw err;
}
}
(async () => {
let response = await wrapMyFetch();
// Do stuff with the response.
})();
I guess, pretty clear so far.
However, I have recently encountered situations where my application does not care about waiting for the results to be fetched and the data containers to be updated etc. Let's say there is one larger loop that runs infinitely and any Promised
requests simply will fill-in the gaps as the application runs.
In that case, we don't really need the async/await
pattern right? We just want to move forward with our loop and stones will fall in place behind us, whenever they are ready to fall in place (or not, in case of an error).
I would like to clarify this: async/await
will just force things to run linearly, right? But if we do not want linearity, and we are ok with spawned tasks - Promises
- to finish their thing in the background in some time when we are resuming with our run-cycle, we don't need that async/await
pattern? Is that correct?
Upvotes: 1
Views: 60
Reputation: 1074285
async
/await
will just force things to run linearly, right?
Not globally, no. await
makes the code in the async
function it's used in wait for the promise you pass it to settle, but that only affects the function you use it in, not anything calling that function.
async
functions are syntactic sugar for writing a function that returns a promise. await
is syntactic sugar for consuming promises. Together, they dramatically simplify using promises (in particular by making rejections errors that automatically propagate through the call tree).
More specifically, an async
function runs its code synchronously until the first await
or return
(or until code runs off the end of the function), at which point it returns a promise. Its logic then waits for the promise to settle, and continues; eventually it settles its promise based on what happened to the last promise it await
ed or return
ed (or fulfills it with undefined
if code execution runs off the end).
If you don't want to wait for a promise to settle, you don't have to, not even in an async
function. Just don't use await
on it. For instance, assume we have this wrapper for fetch
that gets JSON for us (and fixes the API footgun):
async function fetchJSON(...args) {
const response = await fetch(...args);
if (!response.ok) {
throw new Error("HTTP error " + response.status);
}
return response.json();
}
Here's an async
function using it that does an initial query to get a list of things to fetch, and then fetches all of those things in parallel::
async function fetchList(listUrl) {
const list = await fetchJSON(listUrl);
return Promise.all(list.map(item => fetchJSON(itemUrl)));
}
Notice how fetchList
uses await
to wait for the list of things to fetch, but then doesn't wait for the items; it just returns the promise from Promise.all
for the list of items it starts fetching.
Also note how await
within fetchJSON
makes fetchJSON
's logic wait for the fetch
promise to settle, but doesn't make the caller calling fetchJSON
wait unless that caller uses await
. fetchList
only await
s the first call (to get the list), it doesn't wait for the item from the list.
Upvotes: 1
Reputation: 707328
I have been using Promises and async/await, they are pretty much the same thing right?
Well, async/await
are helpful syntax built on top of promises. Async/await
relies on promises in order to work. So, I wouldn't quite call them the same thing, but you can code identically functioning code with await
surrounded by try/catch
and .then().catch()
. You can use either. Both methods rely on promises.
However, I have recently encountered situations where my application does not care about waiting for the results to be fetched and the data containers to be updated etc. Let's say there is one larger loop that runs infinitely and any Promised requests simply will fill-in the gaps as the application runs.
In that case, we don't really need the async/await pattern right? We just want to move forward with our loop and stones will fall in place behind us, whenever they are ready to fall in place (or not, in case of an error).
There is no rule that the caller has to pay attention to a returned promise or has to wait for it before going on with their task. So, if you want to "just let the stones fall as they may in the background" as you say and that's appropriate for your application, you can code that way.
This is often referred to as "fire and forget" coding where you start some asynchronous operation that is going to do something on its own and you don't need to pay attention to when it finishes or if it had an error because that is of no consequence to the calling code.
But, there is a rule that you can't let a promise rejection go unhandled. So, if you're returning a promise and the caller isn't going to do anything with it, then you have to make sure that any rejections are handled by the operation itself (with .catch()
) so that the only thing that ever gets returned back is a resolved promise. Even if all you do is notice the error and do nothing with it, you have to catch the error.
Upvotes: 2