It's a common task for JavaScript developers to send GET and POST requests to retrieve or submit data. There are libraries like Axios that help you do that with beautiful syntax. However, you can achieve the same result with a very similar syntax with Fetch API, which is supported in all modern browsers.

In this post, we'll use the Fetch API to create get() and post() function with a beautiful syntax, much better than the default syntax provided in the Fetch API. We also improve the request performance with a simple caching and we'll take a look at how to use fetch requests with the WordPress REST API. Let's dive in!

JavaScript Fetch API: create GET, POST requests

Why using Fetch API instead of Axios?

Although you can import an external library like Axios to make get and post requests, using the native Fetch API has some benefits:

  • It's native and supported by all modern browsers, no polyfill is needed. You don't have to install an external library and thus, reduce the built file size.
  • It's promise-based, which allows you to use modern async/await syntax for handling asynchronous operations. This makes your code more readable and maintainable.
  • The Fetch API is a web standard, so it's consistent across different browsers. Axios, on the other hand, is a third-party library, and you might need additional configuration or polyfills to ensure consistent behavior across browsers.

Most people love Axios because of its beautiful syntax. But do you know that you can achieve the same thing with just a little code? Let's do that!

Sending Requests with Fetch API

To send a GET request with Fetch API, use the following code:

fetch( 'https://domain.com/path/?param1=value1&param2=value2' )
    .then( response => response.json() )
    .then( response => {
        // Do something with response.
    } );

To send a JavaScript POST request, use the following code:

const params = {
    param1: value1,
    param2: value2; 
};
const options = {
    method: 'POST',
    body: JSON.stringify( params )  
};
fetch( 'https://domain.com/path/', options )
    .then( response => response.json() )
    .then( response => {
        // Do something with response.
    } );

You can see the main difference between GET and POST requests is how the parameters are passed to the fetch call. In most cases, developers expect to pass an object of parameters and send requests in a beautiful syntax like this:

const params = {
    param1: value1,
    param2: value2; 
};

const response = get( url, params );
// or
const response = post( url, params );

To do that, we need some code to transform the original code with fetch to the new syntax.

Creating get and post Functions

Because the codes that send requests are similar between GET and POST, we'll create a common function request to make a request first. And then use it to create get and post functions like this:

const request = ( url, params, method ) => {
    // All logic is here.
};

const get = ( url, params ) => request( url, params, 'GET' );
const post = ( url, params ) => request( url, params, 'POST' );

Now it's time to build the request function.

Note that for each function (get or post), we have different ways to construct parameters: they're in the URL for GET, and in the body for POST. Thanks to URLSearchParams we can transform an object to a query string for the GET request.

Here is the first version:

const request = ( url, params = {}, method = 'GET' ) => {
    let options = {
        method
    };
    if ( 'GET' === method ) {
        url += '?' + ( new URLSearchParams( params ) ).toString();
    } else {
        options.body = JSON.stringify( params );
    }
    
    return fetch( url, options ).then( response => response.json() );
};

const get = ( url, params ) => request( url, params, 'GET' );
const post = ( url, params ) => request( url, params, 'POST' );

The above code returns a promise, and you can use it in your app like this:

get( 'https://domain.com/path', { param1: value1, param2: value2 } )
.then( response => {
    // Do something with response.
} );

You can see it in action on CodeSandbox.

Caching Requests

One problem developers usually need is caching requests, to avoid sending the same request multiple times.

To implement caching, we can create an object to store the data and use it to return the data earlier:

let cache = {};
const request = ( url, params = {}, method = 'GET' ) => {
    // Quick return from cache.
    let cacheKey = JSON.stringify( { url, params, method } );
    if ( cache[ cacheKey ] ) {
        return cache[ cacheKey ];
    }

    let options = {
        method
    };
    if ( 'GET' === method ) {
        url += '?' + ( new URLSearchParams( params ) ).toString();
    } else {
        options.body = JSON.stringify( params );
    }
    
    const result = fetch( url, options ).then( response => response.json() );
    cache[ cacheKey ] = result;

    return result;
};

WordPress REST API

As a WordPress developer, I usually work with the WordPress REST API. While the code above works fine in a general JavaScript app, it needs some changes to work in WordPress.

To send a request to the WordPress API, you need to authenticate the request. Also, the URL for REST requests must contain the WordPress base URL. Here is the updated code:

let cache = {};
const request = ( url, params = {}, method = 'GET' ) => {
    let cacheKey = JSON.stringify( { url, params, method } );
    if ( cache[ cacheKey ] ) {
        return cache[ cacheKey ];
    }

    let options = {
        method,
        headers: { 'X-WP-Nonce': MyApp.nonce }, // Add nonce for WP REST API
    };

    // Setup the rest base URL for requests.
    url = `${ MyApp.restBase }/${ url }`;

    if ( 'GET' === method ) {
        const query = ( new URLSearchParams( params ) ).toString();
        if ( query ) {
            url += MyApp.restBase.includes( '?' ) ? `&${ query }` : `?${ query }`;
        }
    } else {
        options.body = JSON.stringify( params );
    }
    
    const result = fetch( url, options ).then( response => response.json() );
    cache[ cacheKey ] = result;

    return result;
};

To send restBase and nonce to JavaScript, we need to use the wp_localize_script function as follows in your plugin or theme PHP file:

wp_enqueue_script( 'my-app', plugin_dir_url( __FILE__ ) . 'js/app.js', [], '1.0', true );
wp_localize_script( 'my-app', 'MyApp', [
    'restBase' => untrailingslashit( rest_url() ),
    'nonce'    => wp_create_nonce( 'wp_rest' ),
] );

After that, you can make requests like this:

get( 'my-namespace/my-endpoint', { param1: value1, param2: value2 } )
.then( response => {
    // Do something with response.
} );

Conclusion

This post shows you how to make basic GET, POST requests in JavaScript with the Fetch API. It also shows you how to make requests for the WordPress REST API. With little code, we can have a beautiful syntax like in other libraries. You can use this method in your general JavaScript app or in a WordPress plugin. In fact, we use it in our plugins like Meta Box Builder, MB Views, Slim SEO Schema, and Slim SEO Link Manager.

I also wrote an article about modernizing JS code (improving and modernizing a large JavaScript codebase). So if you're interested, you can read it to have a better code.

Happy coding!

2 thoughts on “How to Send GET and POST Requests with JavaScript Fetch API

  1. Is there a way to use more complex 'params' for POST requests?

    For example if body equals (JSON):

    {"jsonrpc":"2.0","id":"2636bfa0-3a90-4c1d-aaf5-23cf0ba4c920","method":"aria2.addUri","params":["token:PASSWORD",["https://example.com/example.mp4"],{"out":"example.mp4"}]}

    I have it working well in PowerShell to add a download for Aria2 but cannot find the syntax for it in JavaScript.

Leave a Reply

Your email address will not be published. Required fields are marked *