简体   繁体   中英

How can I make many jQuery ajax calls look pretty?

I'm making many ajax call based web service. I attached event listeners every dom elements. And every event handlers request ajax call in it. By the way, my source code getting more dirty and complexity. I want to reduce boilerplate code and look more simple with ajax calls.

How can I do that effectively?

The sample code looks like this:

<a href="javascript:void(0);" class="button1">button1</a>
<a href="javascript:void(0);" class="button2">button2</a>
<a href="javascript:void(0);" class="button3">button3</a>
<a href="javascript:void(0);" class="button4">button4</a>

$('.button1').on('click', function() {
    $.ajax({
        url: '/api/1/resource1',
        data: {
            value1: 'value1',
            value2: 'value2'
        },
        success: function (response) {
            $('.some_dom1').html(Handlebars.resource({items:response.items}));
        }
    });
});

$('.button2').on('click', function() {
    $.ajax({
        url: '/api/1/resource2',
        data: {
            value1: 'value1',
            value2: 'value2'
        },
        success: function (response) {
            $('.some_dom2').html(Handlebars.resource({items:response.items}));
        }
    });
});

$('.button3').on('click', function() {
    $.ajax({
        url: '/api/1/resource3',
        data: {
            value1: 'value1',
            value2: 'value2'
        },
        success: function (response) {
            $('.some_dom3').html(Handlebars.resource({items:response.items}));
        }
    });
});

$('.button4').on('click', function() {
    $.ajax({
        url: '/api/1/resource4',
        data: {
            value1: 'value1',
            value2: 'value2'
        },
        success: function (response) {
            $('.some_dom4').html(Handlebars.resource({items:response.items}));
        }
    });
});

Updated:

Every class name and ajax response handler is not same each other. Example code just shows boilerplate code and complexity. This is not the problem of class name or if else statements.

Make common function like this:

String.prototype.endsWith = function(suffix) {
   return this.indexOf(suffix, this.length - suffix.length) !== -1;
};

var doAjax_params_default = {
    'url': null,
    'requestType': "GET",
    'contentType': 'application/x-www-form-urlencoded; charset=UTF-8',
    'dataType': 'json',
    'data': {},
    'beforeSendCallbackFunction': null,
    'successCallbackFunction': null,
    'completeCallbackFunction': null,
    'errorCallBackFunction': null,
};


function doAjax(doAjax_params) {

    var url = doAjax_params['url'];
    var requestType = doAjax_params['requestType'];
    var contentType = doAjax_params['contentType'];
    var dataType = doAjax_params['dataType'];
    var data = doAjax_params['data'];
    var beforeSendCallbackFunction = doAjax_params['beforeSendCallbackFunction'];
    var successCallbackFunction = doAjax_params['successCallbackFunction'];
    var completeCallbackFunction = doAjax_params['completeCallbackFunction'];
    var errorCallBackFunction = doAjax_params['errorCallBackFunction'];

    //make sure that url ends with '/'
    /*if(!url.endsWith("/")){
     url = url + "/";
    }*/

    $.ajax({
        url: url,
        crossDomain: true,
        type: requestType,
        contentType: contentType,
        dataType: dataType,
        data: data,
        beforeSend: function(jqXHR, settings) {
            if (typeof beforeSendCallbackFunction === "function") {
                beforeSendCallbackFunction();
            }
        },
        success: function(data, textStatus, jqXHR) {    
            if (typeof successCallbackFunction === "function") {
                successCallbackFunction(data);
            }
        },
        error: function(jqXHR, textStatus, errorThrown) {
            if (typeof errorCallBackFunction === "function") {
                errorCallBackFunction(errorThrown);
            }

        },
        complete: function(jqXHR, textStatus) {
            if (typeof completeCallbackFunction === "function") {
                completeCallbackFunction();
            }
        }
    });
}

then in your code:

$('.button').on('click', function() {
  var params = $.extend({}, doAjax_params_default);
  params['url'] = `your url`;
  params['data'] = `your data`;
  params['successCallbackFunction'] = `your success callback function`
  doAjax(params);
});

Use a common class:

<a href="javascript:void(0);" class="button">button1</a>
<a href="javascript:void(0);" class="button">button2</a>
<a href="javascript:void(0);" class="button">button3</a>
<a href="javascript:void(0);" class="button">button4</a>

add listener to this class:

$('.button').on('click', function() {
//find the index of the element and use it 
    var btnNumber= $( ".button" ).index(this)+1;

    $.ajax({
        url: '/api/1/resource'+btnNumber,
        data: {
            value1: 'value1',
            value2: 'value2'
        },
        success: function (response) {
            $('.some_dom'+btnNumber).html(Handlebars.resource({items:response.items}));
        }
    });
});

You can also use any kind of attribute and use it later for any data or parameter

like :

<a href="javascript:void(0);" abc="hello1" class="button">button1</a>
<a href="javascript:void(0);" abc="hello2" class="button">button2</a>
<a href="javascript:void(0);" abc="hello3" class="button">button3</a>
<a href="javascript:void(0);" abc="hello4" class="button">button4</a>

and then use it for any purpose

$('.button').on('click', function() {
    var dVal=$(this).attr('abc');
//use dVal any where you want.
    alert(dVal);

});

You can follow this change:

<a href="javascript:void(0);" data-url="/api/1/resource1" class="button">button1</a>
<a href="javascript:void(0);" data-url="/api/1/resource2" class="button">button2</a>
<a href="javascript:void(0);" data-url="/api/1/resource3" class="button">button3</a>
<a href="javascript:void(0);" data-url="/api/1/resource4" class="button">button4</a>

Make use of data-* attribute to hold the specific url for each link which is going to be clicked. Now just one change and you would have a common click event for all ajax calls:

$('.button').on('click', function() {
  var url = $(this).data('url');
  var index = $(this).index();
  $.ajax({
    url: url,
    data: {
      value1: 'value1',
      value2: 'value2'
    },
    success: function(response) {
       $('.some_dom'+index).html(Handlebars.resource({items: response.items}));
    }
  });
});

As per your update in your question you can try doing this:

    success: function(response) {
       if(url.indexOf('1') != -1){
          $('.some_dom1').html(Handlebars.resource({items: response.items}));
       }else if(url.indexOf('2') != -1){
          $('.some_dom2').html(Handlebars.resource({items: response.items}));
       }else if(url.indexOf('3') != -1){
          $('.some_dom3').html(Handlebars.resource({items: response.items}));
       }
    }

In success you have to check if the current url of ajax call is having something different to other calls, so if that matches then you can differentiate it within the if/else if conditions.

You can give a common button class to all tags and you can have a single event handler. Then on the basis of other class name you can make calls using different url and data.

<a href="javascript:void(0);" class="button button1">button1</a>
<a href="javascript:void(0);" class="button button2">button2</a>
<a href="javascript:void(0);" class="button button3">button3</a>
<a href="javascript:void(0);" class="button button4">button4</a>


var  ajaxFunc = function(url, data, successFun){
     $.ajax({
        url: url,
        data:data,
        success: successFun
    });
}

$('button').on('click', buttonClick);


function buttonClick (){
    var elem = $(event.target),
        url='', data;
    if(elem.hasClass('button1')){
        url = '/api/1/resource1';
        data =  {
            value1: 'value1',
            value2: 'value2'
        }
        ajaxFunc(url, data, successFun1);
    } else if(elem.hasClass('button2')){
        url = '/api/1/resource2';
        data =  {
            value1: 'value1',
            value2: 'value2'
        }
        ajaxFunc(url, data, successFun2)
    } else if(elem.hasClass('button3')){
        url = '/api/1/resource3';
        data =  {
            value1: 'value1',
            value2: 'value2'
        }
        ajaxFunc(url, data, successFun3)
    }
     else if(elem.hasClass('button4')){
        url = '/api/1/resource4';
        data =  {
            value1: 'value1',
            value2: 'value2'
        }
        ajaxFunc(url, data, successFun4)
    }
}

function successFun1(evt){

}
function successFun2(evt){

}

If you are not doing anything different then you can go for only one success function.

The template for anchor tag can be like this

<a data-url="url" data-dataId="dataKey" data-success="functionName" onclick="ajax_call(this);">button</a>

or

<a href="javascript:void(0);" data-completeObj="completeObj" onclick="ajax_call(this);" class="button">button</a>

Then the javascript and jQuery part. Store all the parameters needed to pass for each request with a key, this key must match the html data attribute.

var myBigJsonObj = { 
    data1 : { "foo": "bar" }, 
    data2 : { "foo": "bar", "foo1": "bar1"}                   
};

A user defined success function. Similarly can have error function.

function success() {
    // Do some stuff here
    alert('Success');
}

Finally the ajax request call.

function ajax_call(obj) {
    var url = obj.getAttribute('data-url');
    var data = myBigJsonObj[obj.getAttribute('data-dataID')];
    var success = obj.getAttribute('data-success');

    $.ajax({
        url: url,
        data: data,
        success: window[success].call();
    });
}

You can make an async function that contains the ajax API call. Then from everywhere, you can simply call and use the 'then' method for success and error response implementation.

Like here I will give you a very basic example:

// req is JSON type
// SERVICE_URL is global declared service URL or you can pass it as an argument

async function apiCall(req) {
    var form_data = new FormData;
    for (var key in req) form_data.append(key, req[key]);

    let myPromise = new Promise(function (myResolve, myReject) {
        $.ajax({
            url: SERVICE_URL,
            type: 'POST',
            data: form_data,
            processData: false,
            contentType: false,
            success: function (result) {
                myResolve(result);
            },
            error: function (error) {
                myReject(error);
            }
        });
    });

    return await myPromise;
}

Then from everywhere where you are required to use this ajax call use in asynchronous way, like:

// form is the form reference passed from onsubmit method from HTML
// username & password are input fields with 'name' attribute as 'username' & 'password'

function saveForm(form) {
    event.preventDefault();

    const req = {
        username: form.username.value,
        password: form.password.value
    }

    apiCall(req,).then(
        function (value) { console.log('async success:', value) },
        function (error) { console.log('async error:', error) }
    )
}

This is a completely asynchronous implementation and since it's a common function hence is a most cleaner way to do it.

If you like this solution, Please upvote it. Thanks!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM