0

I have global variable var distances = []. I have function to fill it but it takes some time. And I want to send it to Django view when it's filled. However due to JS asynchronous work I alway send empty array. How can I send filled array without setting timeout? My js code is

var distances = [] //array where some digits will be stored

function getAllDistances() //function where this digits being put in distances arr
//note that every digit is result of request to API of routing service so it takes 
//some time to get thing done

function ajaxTest(){//function for sending array to Django view
    $.ajax({
        url:'test/',
        type:'POST',
        data:JSON.stringify({distances : distances}),
        dataType: 'json',
        success:function (data) {
            console.log("Ajax test success");
            console.log(data.result.text);//view should return some result
        },

        error:function () {
            console.log("Ajax test failure")
        }
    })
}

function doTheJob(){ //main function 
    getAllDistances();
    ajaxTest();
}

So everything is ok with request but it always sends empty array. Is it possible to make js send filled array without setting timeout? I guess callback will do thing here but correct me if I wrong


To make it more clear I'll add function that gets me distances

function getRoutSummary(i, j, q) {
                    var url = 'https://router.project-osrm.org/route/v1/driving/' +
                            coords[i][1] + ',' + coords[i][0] + ';' +
                            coords[j][1] + ',' + coords[j][0] +
                            '?geometries=geojson';
//coord is array of arrays with coordinates like
//[[lat1, long1], [lat2, long2], [lat3, long3]] where lat is latitude and long 
//is longtitude

                    var req = new XMLHttpRequest();    
                    req.responseType = 'json';    
                    req.open('GET', url, true);    
                    req.onload = function () {
                        var jsonResponse = req.response;
                        var distance = jsonResponse.routes[0].distance;
                        distances[q] = distance;
                    };
                    req.send();
            }

And then I call this function in loop

function getAllDistances(){
                var q = 0;
                for (var i = 0; i < coords.length; i++){
                    for (var j = 0; j < coords.length; j++){
                        getRoutSummary(i, j, q);
                        q = q + 1;
                    }
                }
                console.log(distances);
            }
indeedme
  • 25
  • 8
  • 2
    Is `getAllDistances` doing some async work in order to fill up the array? If so, then you should call `ajaxTest` with the array filled when the async response arrived in `getAllDistances`. Maybe you're looking for this: [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – lealceldeiro May 28 '19 at 12:02
  • 1
    You will need to implement some kind of callback that will be directly or inderectly called by `getAllDistances()` when it finishes doing its task; `ajaxTest()` will be called by that callback. This can be implemented using either `async`/`await`, `Promise`, or by passing the callback as a parameter. – Haroldo_OK May 28 '19 at 12:06
  • Under what conditions is "distances" considered full? How do you know when each entry in the array has been filled? Do you know this ahead of time? – Lewis May 28 '19 at 12:16
  • @Lewis well, basically yes. To make it more clear, I have 4 points on map, I am using routing service API to get distances from one point to another and I get 16 results. So length of array will be 16 after work is done – indeedme May 28 '19 at 12:19
  • Then if you don’t have a callback you can use, an alternative would be to use setInterval() and check for array length. – Lewis May 28 '19 at 12:21
  • How are you calling the routing services API? It will probably be a good place to put a callback. Maybe you could add that piece of code to the question, so that we can analyze it. – Haroldo_OK May 28 '19 at 12:33
  • I edited question with more code – indeedme May 28 '19 at 12:42
  • `req.onload` would be a great place to add a callback, but you would have to keep a count of how many callbacks have returned in order to fire a final callback for when the collection is fully assembled. – Haroldo_OK May 28 '19 at 12:48

1 Answers1

3

Use promises with Promise.all()

distancePromise = [];

function getAllDistances() {
//a loop
var promise = getSingleDistance();
distancePromise.push(promise);
//return a array of promises
return distancePromise
}
//send the distances after all the promises have been resolved
Promise.all(distancePromise).then(function(distances) {
//save the distances
})
madalinivascu
  • 32,064
  • 4
  • 39
  • 55