Как я могу узнать, когда изменения в jquery html () закончились? - PullRequest
12 голосов
/ 03 апреля 2010

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

$("#divToChange").html(newHTML);

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

Что я хочу знать, так это то, что происходит событие или какой-то другой способ уведомления, когда изменения в html () закончили рендеринг? Я наткнулся на плагин для часов jQuery, который хорошо работает как обходной путь, но он не идеален. Есть ли способ лучше ?

Ответы [ 2 ]

6 голосов
/ 03 апреля 2010

Как уже упоминался комментатор, JavaScript является однопоточным, поэтому вы не можете получить условия гонки.

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

Если ваш код после вызова html(...) зависит от макета страницы, которая пересчитывается перед продолжением, вы можете сделать что-то вроде этого:

$("#divToChange").html(newHTML);
setTimeout(function() {
    // Insert code to be executed AFTER
    // the page renders the markup
    // added using html(...) here
}, 1);

Использование setTimeout(...) со временем 1 в JavaScript откладывает выполнение до тех пор, пока текущий код JavaScript в вызывающей функции не завершится и браузер не обновит пользовательский интерфейс. Это может решить вашу проблему, хотя трудно сказать, если вы не предоставите воспроизводимый пример ошибки, которую вы получаете.

1 голос
/ 10 января 2018

Прошло 7 лет, и я просто столкнулся со сценарием, в точности похожим на описанный @mikel, где я не мог избежать «решения на основе таймера».Итак, я просто делюсь разработанным мною решением на тот случай, если у кого-то все еще есть проблемы с этим.

Я ненавижу иметь в своем коде setTimeout s и setInterval s.Итак, я создал небольшой плагин, который вы можете разместить там, где считаете нужным.Я использовал setInterval, но вы можете изменить его на setTimeout или другое решение, которое вы имеете в виду.Идея состоит в том, чтобы просто создать обещание и постоянно проверять элемент.Мы выполняем обещание, как только оно будет готово.

// jquery.ensure.js

  $.ensure = function (selector) {
    var promise = $.Deferred();
    var interval = setInterval(function () {
      if ($(selector)[0]) {
        clearInterval(interval);
        promise.resolve();
      }
    }, 1);
    return promise;
  };

// my-app.js

  function runWhenMyElementExists () {
    // run the code that depends on #my-element
  }

  $.ensure('#my-element')
    .then(runWhenMyElementExists);
...