Цикл с несколькими входами замедляет работу каждого () и ajax ()

#javascript #jquery

#javascript #jquery

Вопрос:

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

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

Что не работает, так это то, что когда я перебираю более 5-10 флажков, это кажется чрезвычайно медленным или просто не отправляет ajax-запросы.

Запрограммируйте прослушивание для изменения поля включенной / видимой суммы:

 $(document).on("blur", ".dollar-amount", function(){  
    MainPage.amountInputListener('add');
});
  

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

 var MainPage = {

    amountInputListener: function (type) {

        $(".dollar-amount:visible").each(function () {

            //Get the employee being updated
            var empID = $(this).data('empid');

            //get the amount
            var amount = $(this).val();

            //Send update request to backend
            $.ajax({
                type: "POST",
                url: "update/amount?empid="   empID   "amp;amt="   amount   'amp;type='   type,
                dataType: "html"
            });

        });
    },
}
  

HTML для ввода:

 <input type="text" name="dollar_hour_amountX" value="0" class="form-control dollar-amount disabled" data-empid="1" tabindex="-1" disabled>
  

Примечание: dollar_hour_amountX X — это динамическое число, связанное с идентификатором сотрудника строки. data-empid это то же динамическое число, также используемое в цикле for.

Что я пытался сделать, чтобы цикл работал должным образом:

  • Добавление async: false . Это позволяет ему работать в 100% случаев, но при добавлении большего количества входных данных он становится чрезвычайно медленным.

  • Добавление тайм-аута в 100-1000 мс для всей функции, это просто задерживает время выполнения Ajax-вызова в оба конца.

Я открыт для предложений ванильного JS, если это поможет сделать вызовы моего серверного модуля намного быстрее и последовательнее.

Комментарии:

1. Зачем отправлять все данные в blur? Почему бы просто не отправить данные для того, который был только что размыт, предполагая, что это тот, который изменился

2. Это то, что я считаю лучшим, и моя конечная цель, но я не нашел способа отправлять только недавно размытые данные элемента.

3. e.target в вашем обработчике событий делегата размытия элемент будет размытым, при условии, что вы передаете e в прослушиватель. Передайте это в свой метод и используйте его

4. Таплар прав, никогда не выполняйте ajax-запросы в цикле, либо вы отправляете все данные в одном запросе, либо отправляете только те данные, которые фактически были изменены.

5. Очень признателен за понимание и советы. Я собираюсь внести некоторые коррективы и изменить свой подход. Я знаю, что отправка такого количества Ajax-запросов — это большой запрет, просто нужно было немного присмотреться.

Ответ №1:

                                                // capture the passed in event
$(document).on("blur", ".dollar-amount", function(e){  
                             // give the element to the method
    MainPage.amountInputListener(e.target, 'add');
});

var MainPage = {
                                // accept the element on the arguments
    amountInputListener: function (element, type) {
// use the element in place of `this`

            //Get the employee being updated
            var empID = $(element).data('empid');

            //get the amount
            var amount = $(element).val();

            //Send update request to backend
            $.ajax({
                type: "POST",
                url: "update/amount?empid="   empID   "amp;amt="   amount   'amp;type='   type,
                dataType: "html"
            });

    },
}
  

Комментарии:

1. Я знаю, что люди могут сослаться на «отсутствие объяснения того, что это делает». Но ваши комментарии в другом месте помогли мне, и этот пример кода был тем, с чем я закончил, и помог все сгладить. Я ценю это.

Ответ №2:

Не имеет смысла обновлять все, просто обновите то, что меняется.

 $('.dollar-amount').on("change", function () {
   console.log(this.value, $(this).data('empid'))
   // make the one Ajax request
})
  

Или измените свой серверный интерфейс, чтобы иметь возможность обрабатывать несколько отправляемых данных одновременно, чтобы вы не забивали серверную часть кучей вызовов.

Ответ №3:

«Я просматриваю каждый видимый ввод, чтобы проверить, есть ли в нем значение, а затем отправляю ajax-запрос для обновления серверной части (это тоже работает, но, возможно, подход неправильный?)».

Я бы настоятельно рекомендовал вам изменить этот подход. Я подозреваю, что это исправит ваши проблемы. Не перебирайте все это каждый раз. В этом нет необходимости. Просто, при размытии, просто проверьте, изменился ли этот конкретный ввод, а затем отправьте вызов ajax, ТОЛЬКО если этот конкретный ввод был отредактирован.

Просто передайте «this» в amountInputListener в качестве аргумента, а затем избавьтесь от вышеупомянутой функции «each». Остальное было бы таким же. Вместо $(this) просто передайте значение аргумента, которое представляет «это» из события.

Ответ №4:

Первое и главное — следует избегать использования запроса get http verb для обновления. Это не соответствует стандарту, обычно запросы get используются для извлечения данных.

И следующее, что нужно сделать, это вместо вызова ajax для каждого элемента с callname .в долларовом эквиваленте и для видимости лучше объявить глобальную переменную над блоком foreach типа array объектов, а затем добавить каждый элемент в блоке в эту глобальную переменную, а затем, наконец, выполнить ajax-запрос после завершения выполнения блока for

 
    amountInputListener: function (type) {
        var objList = [];
        $(".dollar-amount:visible").each(function () {

            //Get the employee being updated
            var empID = $(this).data('empid');

            //get the amount
            var amount = $(this).val();

            //Send update request to backend
          objList.push({
            'empId':empId,
            'amt':amount,
            'type': type
          });
        });
       $.ajax({
                type: "post",
                url: "update/amount"
                dataType: "application/json",
                data:{'data':objList}
            });
    },
}

  

Таким образом, вы можете отправить все данные за один раз на сервер, и это действительно повышает производительность.

Примечание: код предназначен только для того, чтобы дать вам представление.