ETA 24 Apr 17
Я хотел немного упростить это с помощью некоторых async
/await
magic, так как это делает его более лаконичным:
Используя тот же самый обещанный-наблюдаемый:
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
Ваша вызывающая функция может быть такой же простой, как:
const waitForMutation = async () => {
const button = document.querySelector('.some-button')
if (button !== null) button.click()
try {
const results = await startObservable(someDomNode)
return results
} catch (err) {
console.error(err)
}
}
Если вы хотите добавить тайм-аут, вы можете использовать простой Promise.race
шаблон, как показано здесь :
const waitForMutation = async (timeout = 5000 ) => {
const button = document.querySelector('.some-button')
if (button !== null) button.click()
try {
const results = await Promise.race([
startObservable(someDomNode),
new Promise((resolve, reject) => setTimeout(
reject,
timeout,
new Error('timed out waiting for mutation')
)
])
return results
} catch (err) {
console.error(err)
}
}
Оригинал
Вы можете сделать это без библиотек, но вам придется использовать кое-что из ES6, поэтому помните о проблемах совместимости (например, если ваша аудитория - в основном амиши, луддиты или, что еще хуже, пользователи IE8)
Во-первых, мы будем использовать API MutationObserver для создания объекта-наблюдателя. Мы заключим этот объект в обещание, и resolve()
когда будет запущен обратный вызов (h / t davidwalshblog), статья Дэвида Уолша о мутациях в блоге :
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
Затем мы создадим файл generator function
. Если вы еще не использовали их, значит, вы упускаете - но краткий синопсис: он работает как функция синхронизации, и когда он находит yield <Promise>
выражение, он ожидает неблокирующим образом, чтобы обещание было выполнено. выполнено ( Генераторы делают больше, но это то, что нас здесь интересует ).
let targ = document.querySelector('#domNodeToWatch')
function* getMutation() {
console.log("Starting")
var mutations = yield startObservable(targ)
console.log("done")
}
Сложность генераторов заключается в том, что они не «возвращаются», как обычные функции. Итак, мы будем использовать вспомогательную функцию, чтобы иметь возможность использовать генератор как обычную функцию. (опять же, h / t в dwb )
function runGenerator(g) {
var it = g(), ret;
(function iterate(val){
ret = it.next( val );
if (!ret.done) {
if ("then" in ret.value) {
ret.value.then( iterate );
}
else {
setTimeout( function(){
iterate( ret.value );
}, 0 );
}
}
})();
}
Затем в любой момент до того, как может произойти ожидаемая мутация DOM, просто запустите runGenerator(getMutation)
.
Теперь вы можете интегрировать мутации DOM в поток управления синхронного стиля. Как насчет этого.