Search code examples
javascriptjsonajaxspring-mvcstringify

Ajax returns only first index of stringified array to the Spring controller


Here's the whole JS code:

function getPoolsData(){
$.getJSON('../json/data.json', function(data) {

var date_from = new Date();
console.log(date_from);
var pools_hashrates = [{"date_from" : date_from}];

data.pools.forEach(function(pool){

var api_url = pool.api;
var poolName = pool.name;

if(pool.type == "forknote"){

    $.getJSON(api_url + 'stats', function(data) {

            var poolHashrate = data.pool.hashrate;

            pools_hashrates.push({"poolName" : poolName, "hashrate" : poolHashrate});

            console.log("Pool name: " + poolName + " Pool hashrate: " + parseInt(poolHashrate));
    });
}
else{
    $.getJSON(api_url + 'pool/stats', function(data) {

            var poolHashrate = data.pool_statistics.hashRate;

            console.log("Pool name: " + poolName + " Pool hashrate: " + parseInt(poolHashrate));

            pools_hashrates.push({"poolName" : poolName, "hashrate" : poolHashrate});

    });
}

});

console.log(pools_hashrates);

$.ajax({
  type: "POST",
  contentType : 'application/json; charset=utf-8',
  dataType : 'json',
  url: "/save",
  data: JSON.stringify(pools_hashrates),
  success :function(result) {
      console.log("Success!");
 }
});

});
}

Here's controller method:

@RequestMapping("/save")
public @ResponseBody String getPoolsData(@RequestBody String string){

    System.out.println("Triggered: " + string);
    return "Success mvc";
}

And a controller output:

Triggered: [{"date_from":"2018-04-13T11:05:00.652Z"}]

The problem is, only the first index of an array is sent to the controller, while the array is about 20 in length. console.log(pools_hashrates) prints whole array. The script is invoked via button.


Solution

  • Ajax calls are async, which mean that it's going to fire all 3 of them up at once, the call to getPoolsData will not wait for the get to finish, you need to set the ajax calls to be async.

    Like this

    $.ajaxSetup({
        async: false
    });
    

    Note that this will set all ajax calls to be async, the better thing to do would be to rewrite your calls as such

    $.ajax({
        url: "...",
        type: "GET",
        data: ...,
        async: false
    });
    

    to make only those calls async

    Or you could use setInterval to keep checking if jQuery.active == 0

    jQuery.active == 0 // this tells you if you have active ajax calls
    

    If would be something like this

    var myTimer = setInterval((function(){ 
        if (jQuery.active == 0){
            $.ajax({
                type: "POST",
                contentType : 'application/json; charset=utf-8',
                dataType : 'json',
                url: "/save",
                data: JSON.stringify(pools_hashrates),
                success :function(result) {
                    console.log("Success!");
                }
            });
            clearInterval(myTimer); // stop the interval once you the get calls finished and you send the ajax call
        }
    }, 1000)); // 1000 is the interval at which to check set in miliseconds