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.

JavaScript Fetch API: create GET, POST requests

Using the Fetch API, you don't have to install an external library and thus, reduce the built file size. And you can still have a beautiful syntax with 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 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, we have a different way 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 ) {
        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;
};

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.

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!

MB.Banner-General-bottom

Leave a Reply

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