У меня есть глобальная переменная var distances = []. У меня есть функция, чтобы заполнить его, но это занимает некоторое время. И я хочу отправить его в представление Django, когда оно будет заполнено. Однако из-за асинхронной работы JS я всегда отправляю пустой массив. Как я могу отправить заполненный массив без установки времени ожидания? Мой js-код
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.info("Ajax test success");
console.info(data.result.text);//view should return some result
},
error:function () {
console.info("Ajax test failure")
}
})
}
function doTheJob(){ //main function
getAllDistances();
ajaxTest();
}
Итак, с запросом все в порядке, но он всегда отправляет пустой массив. Можно ли заставить js отправлять заполненный массив без установки времени ожидания? Я думаю, обратный вызов здесь поможет, но поправьте меня, если я ошибаюсь
Чтобы было понятнее, я добавлю функцию, которая вычисляет расстояния.
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();
}
И затем я вызываю эту функцию в цикле
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.info(distances);
}
Вам нужно будет реализовать какой-то обратный вызов, который будет прямо или косвенно вызываться getAllDistances(), когда он завершит выполнение своей задачи; ajaxTest() будет вызываться этим обратным вызовом. Это можно реализовать с помощью async/await, Promise или путем передачи обратного вызова в качестве параметра.
При каких условиях «расстояния» считаются полными? Как узнать, когда каждая запись в массиве заполнена? Вы знаете это заранее?
@ Льюис, ну, в основном да. Чтобы было более понятно, у меня есть 4 точки на карте, я использую API службы маршрутизации, чтобы получить расстояния от одной точки до другой, и я получаю 16 результатов. Таким образом, длина массива будет равна 16 после выполнения работы.
Затем, если у вас нет обратного вызова, который вы можете использовать, альтернативой может быть использование setInterval() и проверка длины массива.
Как вы вызываете API службы маршрутизации? Вероятно, это будет хорошее место для обратного вызова. Может быть, вы могли бы добавить этот фрагмент кода к вопросу, чтобы мы могли его проанализировать.
Я отредактировал вопрос с большим количеством кода
req.onload было бы отличным местом для добавления обратного вызова, но вам нужно будет подсчитывать, сколько обратных вызовов вернулось, чтобы запустить последний обратный вызов, когда коллекция будет полностью собрана.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Используйте обещания с 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
})
Выполняет ли
getAllDistancesнекоторую асинхронную работу, чтобы заполнить массив? Если это так, то вы должны вызватьajaxTestс заполненным массивом, когда асинхронный ответ поступил вgetAllDistances. Возможно, вы ищете это: Как вернуть ответ на асинхронный вызов?