1
\$\begingroup\$

I am more than willing to use both a Promise library and an AJAX calls one if the situation calls for it. This base class sits at the very bare bones of my system and it needs to be done right.

My goal here was to create a bass class in JS that can be extended to help with AJAX calls using Promises. And so I did. But it has one big issue:

It doesn't really handle errors. jQuery.AJAX's error function cannot handle 500 errors and such. In my implementation, when I hit the error spot, I just reject the promise. This doesn't work.

Here's what I cooked:

class Promise_Helped_AJAX_Call {

    constructor(ajax_url, data_package, callback_object, ajax_prerequisites = {'type': 'POST', 'dataType': 'json'}) {
        this.ajax_url = ajax_url;
        this.data_package = data_package;
        this.callback_object = callback_object || undefined;

        this.ajax_prerequisites = ajax_prerequisites;
    }

    call() {
        return new Promise((resolve, reject) => {
            jQuery.ajax({
                url: this.ajax_url,
                type: this.ajax_prerequisites.type,
                dataType: this.ajax_prerequisites.dataType,
                data: {
                    action: this.data_package.ajax_action,
                    security: this.data_package.ajax_nonce,
                    [this.data_package.backend.data_handle]: JSON.stringify(this.data_package.backend.data),
                },
                success: (response) => {
                    this.data_from_response = response;
                    resolve(response);
                },

                error: (response) => {
                    this.data_from_response = response;
                    reject(response);
                }
            });
        });
    }

    ajax_success(response) {
    }

    ajax_error(response) {
    }

    get response_data() {
        if (this.data_from_response.length == 0) {
            return undefined;
        }

        return this.data_from_response;
    }

    set ajax_data_package(new_data_package) {
        this.data_package.backend.data_handle = new_data_package.data_handle;
        this.data_package.backend.data = new_data_package.data;
    }
}

The ajax_success and ajax_error are to be extended by other classes, so maybe you could push the respones to a handler or other things but my base extensions as of now does nothing:

class Base_Ajax_Requester extends Promise_Helped_AJAX_Call {
    ajax_success(response) {
    }

    ajax_error(response) {
    }
}

And my request function:

/**
 * Retrieves all registered demos' data.
 */
const getDemosData = () => {
    return new Base_Ajax_Requester(
        localized_data.ajax_url,
        {
            'ajax_action': 'demos_data_endpoint',
            'ajax_nonce': localized_data.ajax_nonce,
            'backend': {
                'data_handle': 'demos_data_endpoint_request_data',
                'data':
                    {
                    }
            }
        },
        null,
        {
            'type': 'POST',
            'dataType': 'json'
        }
    );
}

Which I'd call like: getDemosData().call().then(response =>....

This doesn't handle errors properly nor is it in any way pretty and, to me, returning a promise that can resolve eventually just...smells -- not sure if it's a just concern, just feels that way.

How can I improve this for it to at least handle errors?

\$\endgroup\$
6
  • \$\begingroup\$ jQuery.ajax() already returns a promise. You don't need to wrap it in another promise \$\endgroup\$
    – jfriend00
    Sep 15, 2019 at 21:44
  • \$\begingroup\$ @jfriend00 Don't the .fail and .done wrappers return that? Also, any other suggestions for this? My main issue is that it doesn't handle errors. \$\endgroup\$
    – coolpasta
    Sep 15, 2019 at 22:34
  • \$\begingroup\$ Just use return jQuery.ajax().then(...). No need to wrap another promise around it. It's wasted and useless code. What do you mean "it doesn't handle errors"? I don't understand the point of storing the success or error response in the object instance data when it's already returned as part of the returned promise. Why invent a different way to use promises? \$\endgroup\$
    – jfriend00
    Sep 16, 2019 at 3:09
  • \$\begingroup\$ returning a promise that can resolve eventually just...smells. Uhhh, that's how asynchronous operations in Javascript and promises work. That's how they do their job. It doesn't smell. That's how you do asynchronous operations in Javascript. That comment sounds like it's from someone who doesn't yet understand asynchronous programming in Javascript and is looking for some synchronous, blocking way to do it that doesn't exist. \$\endgroup\$
    – jfriend00
    Sep 16, 2019 at 3:12
  • \$\begingroup\$ I do not understand what error handling you think is missing. With many Ajax libraries, a response from the server, whether it be a 4xx or a 5xx response is not considered an error because you got a response from the server. An error would be not getting a response at all (like a networking error or a server down or a DNS name not found). If you want to turn 4xx or 5xx responses into rejected promises, you can do that just fine. You just check the status in the response and turn it into an error at that point. \$\endgroup\$
    – jfriend00
    Sep 16, 2019 at 3:16

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Browse other questions tagged or ask your own question.