Показ мод "ожидание" _before_ моя длинная сортировка таблицы начинается (и исчезает после) - PullRequest
0 голосов
/ 23 июня 2019

Я просто хочу сделать три вещи по порядку.

В моей таблице тысячи строк, и для ее сортировки требуется некоторое время.Я хотел бы, чтобы мой «ожидающий» модал отображался во время сортировки, но страница ожидает завершения сортировки, прежде чем пытаться отобразить модал.

Вот jsfiddle .(Вы можете увеличить или уменьшить bignumber, чтобы получить задержку сортировки, которую вы можете видеть, но это не раздражает.)

Я впервые попробовал:

//CSS:   body.loading .waitingModal {display: block;}

$('body').toggleClass("loading");         // happens second!
sortTable(currentdirection,columnno);     // takes ages and happens first
$('body').toggleClass("loading");         // happens third

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

Благодаря этому вопросу моя следующая попытка сработала один раз, но затем модальный режим загрузки больше не появлялся:

$('body').toggleClass("loading");   
setTimeout(function() {           //loading works but not if you click again
    sortTable(order,1);
    $('body').toggleClass("loading");
}

Веб-страницы, на которых люди советуют мне использовать jQuery.Deferred вместо того, чтобы запутаться в аду обратного вызова, и так как я не мог видеть, куда поместить обратный вызов, и ад обратного вызова не кажется забавным, я согласился с этим.

Я читаю вопросы по Какиспользуйте jQuery deferred и , затем vs done и, что наиболее многообещающе, Пример 1 этого ответа из цепочки , но все, кажется, предполагают, что у меня уже есть отложенное / обещание, уже появляющееся из некоторого ajaxили что-то в этом роде.

Моя первая попытка связать некоторые .then(...) вызовы не сработала, потому что буквально ничего не произошло:

$.Deferred().then(function(){
    $('body').toggleClass("loading");    //doesn't happen
}).then(function(){
    sortTable(order,1);                  //doesn't happen
}).then(function(){
    $('body').toggleClass("loading");    //doesn't happen
});

При использовании параметра beforeStart мой модал отображался,но ничего больше:

$.Deferred(function(it){
    $('body').toggleClass("loading");    //happens first, hooray!
}).then(function(){
    sortTable(order,1);                  //doesn't happen
}).then(function(){
    $('body').toggleClass("loading");    //doesn't happen
});

Затем я попытался связать несколько отсроченных then s, явно разрешив и передав отложенное, но я явно не понимаю, как это работает:

$.Deferred().then(function(it){
    $('body').toggleClass("loading");    //still happens second
    it.resolve();
    return it.promise();
}).then(function(){
    sortTable(order,1);                  //happens first
}).then(function(){
    $('body').toggleClass("loading");    //happens third
});

LaВ действительности, я пытался разрешить deffered события изменения в теле

function loadingNow(){
    var deferred = $.Deferred();
    $('body').toggleClass("loading")     // happens
      .change(function(){
        deferred.resolve()
    });
    return deferred.promise();
}            
loadingNow().then(function(){
    sortTable(order,1);                  //doesn't happen
}).then(function(){
    $('body').toggleClass("loading");    //doesn't happen
});

Не имеет значения, переключаю ли я класс после добавления обработчика события изменения:

function loadingNow(){
    var deferred = $.Deferred();
    $('body').change(function(){
        deferred.resolve()
    }).toggleClass("loading");    // happens
    return deferred.promise();
}            
loadingNow().then(function(){
    sortTable(order,1);                  //doesn't happen
}).then(function(){
    $('body').toggleClass("loading");    //doesn't happen
});

Честно говоря, я не ожидал, что будет настолько сложно убедить jQuery сделать три вещи по порядку.Возможно, есть намного более простая вещь, о которой я не думал.Я не возражаю, если обратные вызовы или Deferred сделаны правильно, но если они краткие и относительно ясные, это будет огромным бонусом.

1 Ответ

1 голос
/ 23 июня 2019

У вас почти было это .Большая проблема заключается в том, что прослушивание события change на <body> не срабатывает при изменении класса.Это событие предназначено для элементов формы, таких как текстовые вводы.

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

function loadingNow(){
   var deferred = $.Deferred();
   $('body').one('DOMSubtreeModified', function(){
       deferred.resolve()
   }).toggleClass("loading");
   return deferred.promise();
}           

$("#sortButNoLoading").click(function(){
   order *= -1;
   loadingNow().then(function() {
      sortTable(order,1);   
      $('body').toggleClass("loading"); //happens third
   })
})

Примечания для правильной реализации:

  1. DOMSubtreeModified будет срабатывать каждый раз, когда что-либо меняется в любом месте на <body> или ниже, поэтому убедитесь, что вы прекратили прослушивать это после того, как вызвали функцию в ответ на это.Вы можете использовать $().one() вместо $().on() для автоматического уничтожения слушателя после его запуска один раз.
  2. Согласно этот комментарий , DOMSubtreeModified устарел, и вам следует перейти на что-то другое.
  3. Смотрите "рабочую" скрипку здесь .
...