DEV Community

Discussion on: Fetch API is new old version of AJAX

Collapse
 
loucyx profile image
Lou Cyx

Adding a little, this piece of code:

fetch("someapi.com")
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));
Enter fullscreen mode Exit fullscreen mode

Can be written like this:

fetch("someapi.com")
    .then(response => response.json())
    .then(console.log)
    .catch(console.error);
Enter fullscreen mode Exit fullscreen mode

Or even like this:

fetch("someapi.com")
    .then(response => response.json())
    .then(console.log, console.error);
Enter fullscreen mode Exit fullscreen mode

And from my point of view, that's way more readable than the async/await approach, tho I know that people not familiar with async code coming from other languages find async/await easier to read.

Cheers!

Collapse
 
vetras profile image
vetras

I don't think it is easier to read. Besides if you have this:

fetch("someapi.com")
    .then(foo);
bar();
Enter fullscreen mode Exit fullscreen mode

The order of execution requires you to know that there is a promise here so that the functions are called in this order:
1- fetch
2- bar
3- foo

Collapse
 
loucyx profile image
Lou Cyx • Edited

Hiding async code with syntax sugar is not the solution to that problem... and your over simplistic example is not taking into consideration that with async/await you have to wrap stuff in a try/catch, so let's say you "solve" your foo/bar problem with async/await:

const response = await fetch("someapi.com"); // fetch runs first
foo(response); // then foo
bar(); // then bar
Enter fullscreen mode Exit fullscreen mode

The order is great! ... or is it? Was the intention to run the bar function either way? Or maybe just when fetch doesn't fail?

try {
    const response = await fetch("someapi.com");
    foo(response);
    // should bar() go here?
} catch (error) {
    console.error(error);
} finally {
    // or here?
}
// or maybe here?
Enter fullscreen mode Exit fullscreen mode

And with .then you have the same "issue":

// Maybe bar should go after foo?
fetch("someapi.com")
    .then(foo)
    .then(bar)
    .catch(console.error);

// Maybe bar should go after catching foo errors?
fetch("someapi.com")
    .then(foo, console.error)
    .then(bar);

// Maybe it should run either way?
fetch("someapi.com")
    .then(foo, console.error)
    .finally(bar);

// Or maybe, we actually wanted to run bar in parallel instead of waiting?
fetch("someapi.com").then(foo, console.error);
bar();
Enter fullscreen mode Exit fullscreen mode

From my point of view, this last snippet is still way more clear and less convoluted than the try/catch/async/await one. Maybe you still prefer that one, but as I mentioned we need to compare them in less simplified scenarios, and in that case both are kinda equally complex, but the then/catch approach requires less code while still being readable.

Cheers!

Thread Thread
 
vetras profile image
vetras

Well, you are not wrong because this is pretty much a personal preference.
I just do not agree with you. 😎

Hiding async code with syntax sugar
It's not hiding, it's making it clear that it is async.

with async/await you have to wrap stuff in a try/catch
Only if you can handle the error and know what to do, otherwise it is better to let it bubble up.

Lastly, all the possible options you mention although correct, I think they miss the point.

If you have this:

fetch("someapi.com")
    .then(foo);
bar();
Enter fullscreen mode Exit fullscreen mode

The point is to refactor into async/await but keep the exact same behaviour.
It does not matter much what that behaviour is on the example (functions don't even have a body here).

Cheers! 🍻 happy coding

Thread Thread
 
loucyx profile image
Lou Cyx • Edited

My point was that mainly, in real world scenarios, you have to handle errors, so you'll have to write that try/catch at some point. I also shown several scenarios that might be tricky with either approach. Not to mention that is pretty common to forget that as soon as you make a function async, you make it return a Promise as well, even if you're not actually using promises inside, or if you wanted to handle it internally, so is more of a "footgun" than then/catch. Going back to the simplistic example:

fetch("someapi.com").then(foo);
bar();
Enter fullscreen mode Exit fullscreen mode

Maybe your intention IS to run both fetch and bar "at the same time", which is quite easy to achieve that way, but if you used await, then running bar at the same time is a little bit more complicated. Not to mention, you can combine async/await with then/catch as well, so is not that we need to chose one OR the other:

await fetch("someapi.com").then(foo);
bar();
Enter fullscreen mode Exit fullscreen mode

But yeah, as you mentioned, is generally a preference thing. I tend to use async/await only when the then alternative actually is less readable (like with AsyncIterables).

Thread Thread
 
dionarodrigues profile image
Diona Rodrigues

Hey @lukeshiru and @vetras, thanks for sharing your points. I think both ways are completely fine and I also think it depends on personal/team preferences.