Вызывайте запрос ajax, только если в список добавлено ajax запросов - PullRequest
1 голос
/ 11 февраля 2020

Настройка


У меня есть форма, которая использует серию флажков для определения числа, выбранного на странице:

math on checkboxes here is correct. should be 4

То, что он делает, выбрано, он вызывает контроллер, который сохранит выбор и вернет новую проверенную сумму на основе его текущих данных.

Код выглядит следующим образом


$('#myId').('click', '.selectorClass input', function() {
    const inputCheckBox = this;
    inputCheckBox.disabled = true;
    $(inputCheckBox).addClass('disabled-checkbox')

    $.ajax({ 
       method: "POST",
       url: "@(Url.Action<MyController>(c => c.MyEndPoint(Model.ItemId, null)))",
       data: {
          "boxWasChecked": inputCheckBox.checked
       }
    }).done(function (data) {
       UpdateFields(inputCheckBox, data); //this would update the column footer and 'Total Quantity' field below
    }).fail(function (data) {
       // error check and handle here
    }).always(function(data) {
       inputCheckBox.disabled = false;
       $(inputCheckBox).removeClass('disabled-checkbox')
    });
});

Это прекрасно работает при выборе по одному и даже обычно работает при выборе нескольких.


Проблема


Проблема возникает, когда пользователь выбирает их очень быстро, а затем иногда последний запрос к fini sh не был последним, кто пришел / забрал данные из базы данных на стороне контроллера, и поэтому он возвращает неверную математику для всего.

См. Изображение ниже, где математика должна быть 11 (помните, что она добавляет значение каждого поля, а не количество отмеченных блоков), но сообщает 6.
Если бы я должен был выбрать последний флажок , он будет правильно сообщать 12, потому что он имеет все правильные данные для вызова.

incorrect math for checkboxes. should be 11


Часть, где я застрял


Я думаю, что мне нужно каким-то образом составить список ajax вызовов, а затем отозвать запрос только в том случае, если есть запрос, добавленный после него, ИЛИ все остальные запросы перед ним были выполнены. Я не знаю, как это сделать с ajax вызовами.

Я играл с Promises / Fetch API и пытался заставить это работать, но мог получить обещание добавить к стек в Promise.all[myListOfAjaxCalls].

Сводка кода, над которым я работаю

var listOfPromiseCalls = []

$('#myId').('click', '.selectorClass input', function() {
     // my checkbox is clicked
    listOfPromiseCalls.push(myAjaxCall/myPromise)
    // Psudeo code   
    // begin request if it is the only one in the list
    // else
        // kick off other requests that are in existing list infront of it
    // if other requests finish before another input is clicked, begin this request
});

1 Ответ

2 голосов
/ 11 февраля 2020

Я думаю, что вы находитесь на правильном пути, создав список со всеми запросами, но поскольку вы используете jQuery для асинхронного вызова c, вам следует использовать оператор $.when для ждите, пока все запросы не будут завершены. Promise.all не будет работать, потому что $.ajax не реализует тот же интерфейс, что и new Promise(), поэтому вам нужно обработать его с помощью оператора jQuery.

Вы можете использовать список с все асин c вызовы, как вы описали выше, а затем выполните что-то вроде:

$.when(...listOfPromiseCalls)
  .done((...allResponses) => {
    // do something 
  })
  .catch(errors => {
    // handle errors
  });

Обратите внимание, что я использую операторы распространения от es6 до распространение всех запросов до when, а также агрегирование всех ответов в списке ответов.

О синтаксисе распространения: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax

Если вы не можете использовать синтаксис es6, я рекомендую вам изучить и использовать метод apply для функций js, который дает тот же результат.

...