Foreach, подождите каждую итерацию до получения ответа (синхронизация js) - PullRequest
0 голосов
/ 17 декабря 2018

У меня есть цикл foreach, и я перебираю элементы.Для каждого элемента я сохраняю его в базу данных, используя ajax.Однако я хочу, чтобы каждая итерация ожидала, пока предыдущая будет сохранена в базе данных и получит ответ.

Позвольте привести упрощенный пример:

$('#myBtn').click(function() {
   let elements = $('.checkboxes:checked');

   elements.forEach(function(i, el) {
      let id = $(el).data('id');

      saveToDatabase(id);
      // I want it to pause here until it receives a response from other function 
      // before going to the next iteration..
   })

})   


function saveToDatabase(id) {
   axios.get('/save-to-db/' + id)
       .then(response => {
           return true;
       }).catch(err => {
           return false;
   });
}

Я хочу, чтобы элементы forEach переместились вследующая итерация после получения «возврата» из функции saveToDatabase.

(кстати, я знаю, что этот пример слишком упрощен и не имеет смысла в реальной жизни, так как я могу сохранять идентификаторы в базе данных наваломОднако я просто хочу понять, как справиться с таким делом).

Ответы [ 3 ]

0 голосов
/ 17 декабря 2018

Поскольку forEach использует функцию обратного вызова, использовать ее для синхронизации вызовов довольно сложно.Вместо этого я думаю, что использование простого цикла for будет работать.

$('#myBtn').click(async () => {
    let elements = $('.checkboxes:checked');
    for (let element of elements) {
        let id = $(element).data('id');
        await saveToDatabase(id);
    }
});
0 голосов
/ 17 декабря 2018

Существует довольно много способов заставить запросы ждать друг друга.Самым простым для вас является сохранение ссылки на последний запрос-обещание для вызова следующего, когда предыдущий разрешен (внутри функции then).

$('#myBtn').click(function() {
   let elements = $('.checkboxes:checked');
   let previousCall = Promise.resolve();

   elements.forEach(function(i, el) {
      let id = $(el).data('id');

      previousCall = previousCall.then(() => saveToDatabase(id));
      // I want it to pause here until it receives a response from other function
      // before going to the next iteration..
   })

})   


function saveToDatabase(id) {
   return axios.get('/save-to-db/' + id)
       .then(response => {
           return true;
       }).catch(err => {
           return false;
   });
}
0 голосов
/ 17 декабря 2018

Определите saveToDatabase(id) как асинхронную функцию и в этом примере используйте await.

Ссылка: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

РЕДАКТИРОВАТЬ: Кроме того, вернуть обещание из saveToDabase функции.

Реализация функции saveToDatabase:

$('#myBtn').click(function() {
   let elements = $('.checkboxes:checked');

   for (let element of elements) {
       await saveToDatabase(id);
   }
}) 

async function saveToDatabase(id) {
   return axios.get('/save-to-db/' + id)
       .then(response => {
           return true;
       }).catch(err => {
           return false;
   });
}

Кроме того, я забыл: функция, в которой вы используете await, должна иметь перед ней асинхронность.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...