Fetch API in Node.js
Fetch() support is now available in Node.js as an experimental core feature. Fetch() is a well-liked cross-platform HTTP client API that functions in browsers and Web/Service Workers.
Many people who want to build cross-platform HTTP request code and are familiar with the fetch() API structure and call patterns have long demanded the addition of fetch() support.
The node-fetch module was created specifically to backfill this feature in Node.js, which is why it exists. The good news is that for ahead, Node.js core will support the API, eliminating the requirement for a separate module.
This article examines the fetch() API and explains why it is a useful addition that you ought to use.
We will cover the following:
- History
- Introducing the Fetch API
- What is Fetch API?
- What Exactly is fetch()?
- How to Use Fetch?
- Benefits of Utilizing the Node.js Fetch API
- Drawbacks of Fetch API
- Can We Use Fetch in Node.js?
- Why Should You Care?
History
Early web developers had to utilize difficult ways to communicate across several networks because executing asynchronous requests across websites was challenging.
In 1998, Internet Explorer 5 introduced XMLHttpRequest, an API designed to get around this limitation. XMLHttpRequest was first intended to get XML data over HTTP, hence the name. Support for other data formats, principally JSON, HTML, and plaintext, was added after it was initially released.
Back then, the XMLHttpRequest API functioned well, but it became increasingly challenging to use as the web expanded. As a result, JavaScript frameworks, most notably jQuery, had to abstract it to make implementation and success/error handling more streamlined.
Introducing the Fetch API
The Fetch API, which was introduced in 2015 as a more contemporary replacement for XMLHttpRequest, has since taken over as the de facto standard for asynchronous call-making in web applications.
The fact that Fetch uses promises to create a clearer, cleaner API while avoiding callback hell is a key benefit it has over XMLHttpRequest. Although the Fetch API has been around for some time, it hasn't been incorporated into the core of Node.js because of several limitations.
It was mentioned in a question response on Hacker News by one of Node's main contributors that the browser's Fetch API implementation depends on a browser-based Web Streams API and the AbortController interface (for aborting fetch requests), both of which were not previously included in Node.js.
As a result, choosing the appropriate method to include it in the core of Node.js proved to be challenging.
The request module was the most often used technique for sending HTTP requests in Node for a very long time before the Fetch API was introduced. However, the overall JavaScript ecosystem quickly changed, and newly developed patterns rendered request unnecessary.
Async/await is an important example of this; the request API did not support it, and the project was later discontinued as a result of these limitations.
Undici
Undici, a newer and quicker HTTP/1.1 client for Node.js that supports pipelining and pooling among other capabilities, was released in 2018. After much effort from the core team, Undici made it possible to implement fetch() in Node.js.
What is Fetch API?
An application programming interface called Fetch API is used to get network resources. Making GET, POST, and other HTTP queries are made easier by it.
The Fetch API supports modern standards like Promise, resulting in cleaner code that doesn't need callbacks.
In all popular browsers, the Fetch API has native support. The node-fetch package is used by JavaScript developers to create server-side code. Millions of people download the product each week, demonstrating its enormous popularity.
With version 17.5, Node.js has made experimental support for the Fetch API available. Since then, we no longer need to install a third-party library to create server-side JavaScript code that utilizes the Fetch API.
What Exactly is fetch()?
A WHATWG-standard interface for retrieving resources, typically through HTTP, is provided by the fetch() API. It is a promise-based client that emphasizes sending simplified HTTP requests while simultaneously supporting several high-level HTTP features.
It is comparable to XMLHttpRequest for people coming from the browser world but standardized with a larger and more flexible feature set.
The very recent addition of this API to several browsers has been one of the things that have prevented developers from progressing. Because of this, the addition of fetch() in Node.js is a positive step toward a more standard HTTP stack across platforms and devices.
The API primarily consists of four interfaces:
- fetch() - the point of entry used to make requests
- Headers class - handle HTTP request/response headers
- Request class - represents an instance of an outgoing request
- Response class - represents an instance of an incoming response
Here is a simple example using these:
const res = await fetch('https://dogs.com/api/breeds/list/all');
const json = await res.json();
console.log(json);
The benefit of fetch()
being standardized is that the majority of resources that are already available for the browser version will also function well in the Node.js implementation. There are many excellent resources available.
How to Use Fetch?
The Fetch API is a high-level function that takes a URL as an input and returns a promise that resolves to the response:
fetch(url)
.then(function(res) {
// handle the response
})
.catch(function(err) {
// handle the error
});
By adding an optional object after the URL, you can modify the fetch process in other ways as well.
For example, you can alter the request methods, request headers, and other aspects. The returned metadata for our request, which includes things like response data, headers, the request data, and other things, is contained in the request's response, which is an object.
Properties of a Response
The response object contains much more than just the JSON body:
fetch('https://example.com')
.then(res => {
res.text() // response body (=> Promise)
res.json() // parse response body (=> Promise)
res.status //=> 200
res.statusText //=> 'OK'
res.redirected //=> false
res.ok //=> true
res.url //=> 'https://new.example.com'
res.type //=> 'basic'
// ('cors' 'default' 'error'
// 'opaque' 'opaqueredirect')
res.headers.get('Content-Type')
})
text()
- returns the response body as a stringjson()
- parses the response body as JSONstatus
- returns the status codestatusText
- returns the status message with respect to the status codeok
- returns true if the request returns2xx
as a status code (a successful request)url
- value of the final URL obtained after the redirectheaders
- a collection of response headers, accessible through theget()
function
Benefits of Utilizing the Node.js Fetch API
For the benefit of the developer community, the Fetch API is now provided as a pre-configured Node module. Among these advantages are:
- Cross-platform Familiarity
Using the built-in fetch() method in Node, developers who have previously used the Fetch API on the frontend will feel right at home. Compared to using external packages, it will be considerably easier to use and more natural in a Node context. - Faster Implementation
As was already said, the new Fetch implementation is also built on Undici, a Node.js HTTP client that is quick, dependable, and spec-compliant. You should therefore expect the Fetch API to perform better as a result. - No Additional Fetch Packages
The introduction of Inbuilt Fetch for Node.js could spell the end for other packages designed for the same purpose, including node-fetch, got, cross-fetch, and others. This means that before using Node to execute network operations, you won't need to run an npm install.
Additionally, the most widely used Node.js fetch package at the moment, node-fetch, just changed to an ESM-only package. This means that the Node require() method cannot import it. HTTP fetching in Node settings will seem much more natural and fluid due to the native Fetch API.
Drawbacks of Fetch API
There are some issues with the browser's Fetch API that will undoubtedly carry over to the new Node.js Fetch implementation:
- Error Handling
Only network errors are regarded as true errors by Fetch, which performs poorly in this area. This means that errors sent by the server are not taken into account; instead, Fetch will only reject a promise if the user is not connected to the internet or if a rare networking error occurs. - Establishing Timeouts
It is also challenging to set timeouts in Fetch to cancel a certain request after a certain amount of time has passed. - No Request Progress
Another significant issue is that, unlike libraries like Axios, Fetch does not provide a way to readily track the status of requests.
Can We Use Fetch in Node.js?
In Node v17, Fetch is already available as an experimental feature. You must first download and update to Node.js version 17.5 if you want to test it out before the official release.
As an alternative, you can update straight from your command line/terminal by using nvm:
nvm install 17.5
By including the --experimental-fetch parameter with the node command, we can now execute Fetch-related code:
node app.js --experimental-fetch
Migrating from Other Libraries
There is no official migration guide in place as of the time of writing. The API may encounter some breaking changes or other updates when it reaches stable release because it is present in the experimental stage. Therefore, it is advised to hold off on moving any active projects until the API is stable.
Why Should You Care?
There are two primary justifications you might think about utilizing fetch() in Node.js:
- Currently, there is a lot of discussion in the community about how to improve Node's HTTP stack in a way that is familiar to client developers while also working with the server programming model, how to get past the limitations of the built-in HTTP model, and how to support HTTP/2-3 without burdening the user. The first stage in that discourse is this experimental core feature, which offers you the chance to test it out and participate in the discussion.
- The implementation of fetch() is based on Undici, a brand-new HTTP/1.1 client that is now integrated into Node.js core and is quick, dependable, and spec-compliant. Undici can frequently provide significant improvements in latency and performance over the current solution because it does away with various out-of-date HTTP primitives and builds directly on top of sockets.
Conclusion
Overall, it's fantastic that Fetch is now being added to the core of Node.js since the developer community had long requested this. We've examined how asynchronous web requests have changed over time in this article, as well as how Fetch ultimately ended up in Node.js.
Since there is still more to be done to make the Fetch API standard-compliant, it might take some time before it is completely reliable in Node.js. There are many interesting updates planned for the near future, one of which being the inclusion of HTTP/2 functionality in Undici and eventually the Fetch API.
Atatus API Monitoring and Observability
Atatus provides Powerful API Observability to help you debug and prevent API issues. It monitors the consumer experience and is notified when abnormalities or issues arise. You can deeply understand who is using your APIs, how they are used, and the payloads they are sending.
Atatus's user-centric API observability tracks how your actual customers experience your APIs and applications. Customers may easily get metrics on their quota usage, SLAs, and more.
It monitors the functionality, availability, and performance data of your internal, external, and third-party APIs to see how your actual users interact with the API in your application. It also validates rest APIs and keeps track of metrics like latency, response time, and other performance indicators to ensure your application runs smoothly.