I suggest that mutating global state like this is the opposite of a pro tip:
constoriginalFetch=window.fetchwindow.fetch=async (...args)=>{// intercept requestconstres=originalFetch(...args)// intercept response e.gif(res.ok){returnres.json()}else//Do whatever you want to handle the error}}
Now, every single client side request that uses fetch under the hood will not work as expected. You've literally broken every request.
In a commercial setting, you're almost guaranteed to be running some vendor scripts on the client. Things like logging services, tracking and marketing, A|B tests, heat mapping or service integrations. All of these will no longer work as expected if they use the fetch API. Not to mention any browser extensions or user scripts that may be loaded on the client...
Even the simple action of transforming the response to JSON like this will break any call to fetch.
Broken Implementation
Just try this example after mutating global.fetch:
Text Error
SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON at JSON.parse (<anonymous>)
JSON Error
TypeError: jsonRes.json is not a function
This is incredibly difficult to reason about as these errors are misleading.
In this case, vendors who use axios are better off because this mutation doesn't affect XMLHttpRequest.
Use Encapsulation
This is closer to what I would consider a professional approach:
// client.tsexportasyncfunctionclient(input:RequestInfo|URL,init?:RequestInit):Promise<Response>{constres=awaitfetch(input,init);// Do whatever you want with resreturnres;}// someFunction.tsimport{client}from'./client';exportasyncfunctionsomeFunction(){returnawaitclient('https://example.com');}
Neither Choice is Superior
The choice between axios and fetch depends on the context of the problem. You've laid out a number of examples that, from your perspective, make axios seem redundant to you. However, your examples actually make a strong case for using axios in a commercial setting to me.
As someone who's created some XMLHttpRequest implementations by hand, I have similar misgivings to using fetch today that I did back then.
It really highlights the convenience that axios provides. I look at your form examples and I see a lot of additional code that the team has to maintain.
I want to reiterate that I don't see any choice as superior to the other before sharing my experience using fetch out of the box in a project.
It almost always ends up with something like this to make a basic request:
constbase64Credentials=btoa(username+':'+password);constheaders=newHeaders({'Authorization':'Basic '+base64Credentials,'Content-Type':'application/json','Custom-Header':'CustomHeaderValue'});fetch('https://example.com/api/resource-a',{method:'POST',headers:headers,body:JSON.stringify(requestBody)}).then(response=>{if (!response.ok){thrownewError('Network response was not ok');}returnresponse.json();}).then(data=>{console.log(data);}).catch(error=>{console.log('There was a problem with the fetch operation:',error.message);});
Then a stakeholder comes along and adds a new business requirement to fetch something from resource-b as well. So the fetch logic is encapsulated:
exportfunctionfetchFromApi(path,jsonBody){constbaseUrl='https://example.com/api/';consturl=baseUrl+path;// Basic Authorization headerconstbase64Credentials=btoa(username+':'+password);constheaders=newHeaders({'Authorization':'Basic '+base64Credentials,'Content-Type':'application/json','Custom-Header':'CustomHeaderValue'});returnfetch(url,{method:'POST',headers:headers,body:JSON.stringify(jsonBody)}).then(response=>{if (!response.ok){thrownewError('Network response was not ok');}returnresponse.json();});}fetchFromApi('/resource-a',aBody).then(handleABody).catch(handleError);fetchFromApi('/resource-b',bBody).then(handleBBody).catch(handleError);
This is the reality that you face when building complex applications with fetch. It's a considerable investment to save 23KB on a request.
That is an excellent point on not mutating the global state. Thanks for the callout. The main point I was trying to make is to always encapsulate(wrap).
I'll do an edit sometime during the day to reflect this.
To reinvent the wheel or not to
This topic is very subjective, so I'll have to answer subjectively. Having written and made HTTP requests in another language (i.e. go and rust) in the past year, returning to fetch didn't seem like a lot of work.
Arguably, many of the JS libraries out there are reinventing the wheel for better or worse.
At the end of the day, it's up to your team to decide how much re-invention is too much reinvention.
On whether one is superior to the other
This is not a subjective one, so here are my plus for fetch
It's in the browser forever, so your code is insured for life
Whatever abstraction you choose to build on it belongs to your team. Fortunately, from most codebases I've worked on, your HTTP client root config is usually the least touched module as your codebase grows.
It's faster: Checking some random benchmarks on the internet, fetch always comes out at least 2x faster than axios. This is not important to me because as your team builds its abstraction over fetch, your requests might get slower.
Some comments have been hidden by the post's author - find out more
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
Never Mutate Global State
I suggest that mutating global state like this is the opposite of a pro tip:
Now, every single client side request that uses fetch under the hood will not work as expected. You've literally broken every request.
In a commercial setting, you're almost guaranteed to be running some vendor scripts on the client. Things like logging services, tracking and marketing, A|B tests, heat mapping or service integrations. All of these will no longer work as expected if they use the
fetchAPI. Not to mention any browser extensions or user scripts that may be loaded on the client...Even the simple action of transforming the response to JSON like this will break any call to
fetch.Broken Implementation
Just try this example after mutating
global.fetch:Calling this function will output:
This is incredibly difficult to reason about as these errors are misleading.
In this case, vendors who use
axiosare better off because this mutation doesn't affectXMLHttpRequest.Use Encapsulation
This is closer to what I would consider a professional approach:
Neither Choice is Superior
The choice between
axiosandfetchdepends on the context of the problem. You've laid out a number of examples that, from your perspective, makeaxiosseem redundant to you. However, your examples actually make a strong case for usingaxiosin a commercial setting to me.As someone who's created some
XMLHttpRequestimplementations by hand, I have similar misgivings to usingfetchtoday that I did back then.It really highlights the convenience that
axiosprovides. I look at your form examples and I see a lot of additional code that the team has to maintain.Your example has zero dependencies:
This example is less complex, more convenient and less maintenance:
Reinventing the Wheel vs Getting Things Done
I want to reiterate that I don't see any choice as superior to the other before sharing my experience using fetch out of the box in a project.
It almost always ends up with something like this to make a basic request:
Then a stakeholder comes along and adds a new business requirement to fetch something from
resource-bas well. So the fetch logic is encapsulated:This is the reality that you face when building complex applications with
fetch. It's a considerable investment to save 23KB on a request.To achieve the same result with
axios:On Not Mutating Global State
That is an excellent point on not mutating the global state. Thanks for the callout. The main point I was trying to make is to
always encapsulate(wrap).In my codebase, it looks something like this.
I'll do an edit sometime during the day to reflect this.
To reinvent the wheel or not to
This topic is very subjective, so I'll have to answer subjectively. Having written and made HTTP requests in another language (i.e. go and rust) in the past year, returning to
fetchdidn't seem like a lot of work.Arguably, many of the JS libraries out there are reinventing the wheel for better or worse.
At the end of the day, it's up to your team to decide how much re-invention is too much reinvention.
On whether one is superior to the other
This is not a subjective one, so here are my plus for
fetch