Я пользовался такой функцией
/*
Асинхронно обрабатывает элементы arr. Каждый элемент обрабатывается после обработки предыдущего
функция callback принимает параметры
el - элемент массива
i - индекс элемента
arr - сам массив
и должна возвращать Promise, разрешаемый после обработки элемента.
Если Promise отклоняется, обработка цикла прерывается
Возвращает Promise, разрешенный после обработки всех элементов или отклоненный, если какой либо элемент
вернул отклоненный Promise
*/
asyncForEach (arr, callback) {
let prom = Promise.resolve(true)
for (let i = 0; i< arr.length; i++) {
let el = arr[i];
prom = prom.then ( _ => callback (el, i, arr))
}
return prom.then ( _ => arr.length);
}
Тогда можно так
const ajaxcall = (el, i) => {
const tableName = el.dataset.table;
return new Promise ((res, rej) => {
$.request('onAjax', {
data: {
'table': tableName
},
success: function(data) {
// ответ сервера об успешном выполнении запроса
},
error: function(data) {
// ответ об ошибке
// rej(data) // Если вызывать, цикл прервется
},
complete: function(data) {
// выполнится независимо от успешного запроса или ошибки
res() // Тут промис разрешился
}
});
})
}
loader.classList.remove('hide');
asyncForEach (arr, ajaxcall )
.then (_ => loader.classList.add('hide');) // что то там гасим, когда все вызовы закончатся.
// .catch (data =>{
// Тут можно обработать, если где то произошла ошибка и цикл прошел не полностью
//})