jQuery сортирует, только если точка останова в Firebug существует

#jquery #firebug

#jquery #firebug

Вопрос:

Я создал скрипт, который отправляет AJAX-запрос и обновляет элемент select списком элементов option. После того, как это было сделано, я пытаюсь отсортировать элементы options с помощью плагина jQuery jQuery.sortElements.js :

 /* If region is specified */
    if (regionId != '0') {
        /* AJAX request to get city list and refresh select state. */
        $.getJSON('/json/cities', {region_id: regionId}, function(json) {
            $("select.changedBy-"   regionSelectId).each(function() {
                var citySelect = $(this);
                $.each(json, function(id, name) {
                    $('<option value="'   id   '">'   name   '</option>').appendTo(citySelect);
                });
            });
        });

        /* Sorting */
        $("select.changedBy-"   regionSelectId).each(function() {
            $(this).find('option').sortElements(function(option1, option2) {
                var option1Value = $(option1).attr('value');
                var option2Value = $(option2).attr('value');
                if (option1Value == '0') return -1;
                if (option2Value == '0') return 1;
                if (option1Value == regionId) return -1;
                if (option2Value == regionId) return 1;
                return $(option1).text() > $(option2).text() ? 1 : -1;
            });
        });
    }
};
  

К сожалению, сортировка работает, только если я ставлю точку останова в Firebug в следующей строке:

 $("select.changedBy-"   regionSelectId).each(function() {
  

В другом случае (обычный режим) он не сортирует элементы опции. Не могли бы вы, пожалуйста, помочь мне найти причину этой проблемы?

Спасибо, Борис.

Ответ №1:

Звучит и выглядит как проблема с синхронизацией. Вы понимаете, что getJSON() вызов является асинхронным, верно? Движок JavaScript доберется до $.getJSON() , выполнит запрос, а затем почти сразу же перейдет к вашему коду сортировки. Выполнить сортировку не удастся, поскольку пока не будет никаких элементов для сортировки, поскольку запрос не завершен.

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

Я бы предложил одно из следующих

  1. Перемещение всего вашего кода сортировки внутрь getJSON() функции обратного вызова сразу после добавления всех новых <option>
  2. Обертывание кода сортировки в функцию и вызов этой функции после завершения создания всех новых <option> ов

Вот код для первого предложения (бесконечно проще — для этого нужно было просто вырезать и вставить ваш код сортировки в тело функции обратного вызова):

  if (regionId != '0') {
        /* AJAX request to get city list and refresh select state. */
        $.getJSON('/json/cities', {region_id: regionId}, function(json) {
            $("select.changedBy-"   regionSelectId).each(function() {
                var citySelect = $(this);
                $.each(json, function(id, name) {
                    $('<option value="'   id   '">'   name   '</option>').appendTo(citySelect);
                });
            });

            /* Sorting */            
             $("select.changedBy-"   regionSelectId).each(function() {
                $(this).find('option').sortElements(function(option1, option2) {
                    var option1Value = $(option1).attr('value');
                    var option2Value = $(option2).attr('value');
                    if (option1Value == '0') return -1;
                    if (option2Value == '0') return 1;
                    if (option1Value == regionId) return -1;
                    if (option2Value == regionId) return 1;
                    return $(option1).text() > $(option2).text() ? 1 : -1;
                });
            });
        });
    }
  

Ответ №2:

Запрос Ajax может быть асинхронным. Используйте синхронный Ajax-запрос

Ответ №3:

JavaScript — это однопоточный язык, ваш код сортировки вызывается, когда еще не создан элемент option, поскольку они создаются по завершении ajax-запроса. Принудительный вызов кода сортировки после создания элемента option заключается в том, чтобы поместить код сортировки в функцию и вызвать его по завершении запроса ajax, после создания элемента option, это будет похоже:

  makeAjaxCall(callBack(){
  createOptionElements();
  SortOptionElements();
});
  

Надеюсь, у вас это сработает. удачи 🙂