DEV Community

Todd Birchard for Hackers And Slackers

Posted on • Originally published at hackersandslackers.com on

Making API Requests with NodeJS

Making API Requests with NodeJS

If you're the type of person to read technical Javascript posts in your free time (you are), you don't need me to tell you that JQuery is dead. JQuery themselves have proclaimed JQuery to be dead. The only cool thing about JQuery is who can remove it from their legacy stack the fastest, which begs the question: why is the third most popular page on this site an old post about JQuery?

Maintaining a blog of tutorials has taught me a lot about the gap between perception and reality. While we content publishers sling Medium posts from our ivory towers, we quickly create a perception of what "everybody" is doing, but it turns out "everybody" only includes individuals who are exceptionally visible. That demographic makes up significantly less than 10-20% of the active workforce. I would have assumed any post with the word "React" would immediately explode, when in reality people are more interested in using Handlebars with ExpressJS (I'm not proud of that post by the way, please don't read it).

I want to provide an alternative to using AJAX calls when interacting with REST APIs to clear my conscious of ever enabling bad behavior in the first place. Hopefully, those who have lost their way might find something to take from it. Considering how deep I've gone down the GraphQL rabbit hole myself, this may be the last chance to bother writing about REST at all.

Library of Choice: node-fetch

Like everything in Javascript, there are way too many packages doing the same thing and solving the same problem. Making API requests is no exception. http is a bit primitive, request breaks when building with Webpack, r2 seems like a pointless clone, and so on. Don't get me started with async libraries with 40 different methods for chaining requests. Who is gunslinging API requests to the point where we need this many options to pipe or parallel API requests anyway?

After using all of these libraries, node-fetch is the weapon of choice for today. To put it simply: it's straightforward, and the only one that actually works out of the box with Webpack without absurd configuration nonsense. The only good drop-in alternative I've bothered with is node-isometricfetch. Isometric Fetch mimics the syntax of node-fetch , but impressively works on both the client and server-side.

Getting Set Up

Start a Node project and install node-fetch:

npm install --save node-fetch

Enter fullscreen mode Exit fullscreen mode

In the JS file we'd like to make a request, we can reference node-fetch using require():

const fetch = require('node-fetch');

Enter fullscreen mode Exit fullscreen mode

Creating a node-fetch Request

We'll start with the most basic GET request possible:

fetch('https://example.com')
  .then(response => response.json())
  .then(data => {
    console.log(data)
  })
  .catch(err => ...)

Enter fullscreen mode Exit fullscreen mode

Indeed, that's all it takes a base level. Without specifying a method, node-fetch assumes we're making a GET request. From we generate JSON from the request body and print the result to the console.

Chances are you're not going to get much value out of any request without passing headers, parameters, or a body to the target endpoint. Here's how we'd make a more complicated (and realistic) POST call:

var url ='https://example.com';
var headers = {
  "Content-Type": "application/json",
  "client_id": "1001125",
  "client_secret": "876JHG76UKFJYGVHf867rFUTFGHCJ8JHV"
}
var data = {
  "name": "Wade Wilson",
  "occupation": "Murderer",
  "age": "30 (forever)"
}
fetch(url, { method: 'POST', headers: headers, body: data})
  .then((res) => {
     return res.json()
})
.then((json) => {
  console.log(json);
  // Do something with the returned data.
});

Enter fullscreen mode Exit fullscreen mode

That's more like it: now we're passing headers and a JSON body. If needed, the fetch() method also accepts a credentials parameter for authentication.

Note that we are avoiding callback hell by keeping logic that utilizes the response JSON in our then() arrow functions. We can chain together as many of these statements as we want.

Properties of a Response

The response object contains much more than just the response body JSON:

fetch('https://example.com')
.then(res => {
  res.text() // response body (=> Promise)
  res.json() // parse via JSON (=> Promise)
  res.status //=> 200
  res.statusText //=> 'OK'
  res.redirected //=> false
  res.ok //=> true
  res.url //=> 'https://example.com'
  res.type //=> 'basic'
                   // ('cors' 'default' 'error'
                   // 'opaque' 'opaqueredirect')

  res.headers.get('Content-Type')
})

Enter fullscreen mode Exit fullscreen mode

res.status is particularly handy when building functionality around catching errors:

fetch('https://example.com')
  .then(reportStatus)

function checkStatus (res) {
  if (res.status >= 200 && res.status < 300) {
    return res
  } else {
    let err = new Error(res.statusText)
    err.response = res
    throw err
  }
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)