ETA 24 Nis 17
Bunu biraz daha özlü hale getirdiği için bunu biraz async
/ await
büyü ile basitleştirmek istedim :
Aynı söz verilen-gözlemlenebilir kullanımı:
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
// For the sake of...observation...let's output the mutation to console to see how this all works
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
Arama işleviniz şu kadar basit olabilir:
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)
}
}
Zaman aşımı eklemek isterseniz, burada gösterildiği gibi basit bir Promise.race
desen kullanabilirsiniz :
const waitForMutation = async (timeout = 5000 /*in ms*/) => {
const button = document.querySelector('.some-button')
if (button !== null) button.click()
try {
const results = await Promise.race([
startObservable(someDomNode),
// this will throw after the timeout, skipping
// the return & going to the catch block
new Promise((resolve, reject) => setTimeout(
reject,
timeout,
new Error('timed out waiting for mutation')
)
])
return results
} catch (err) {
console.error(err)
}
}
orijinal
Bunu kütüphaneler olmadan yapabilirsiniz, ancak bazı ES6 öğelerini kullanmanız gerekir, bu nedenle uyumluluk sorunlarının farkında olun (yani, kitleniz çoğunlukla Amish, luddite veya daha kötüsü IE8 kullanıcılarıysa)
İlk olarak, bir gözlemci nesnesi oluşturmak için MutationObserver API'sini kullanacağız. Bu nesneyi bir söze sararızresolve()
ve geri arama tetiklendiğinde (h / t davidwalshblog) mutasyonlarla ilgili david walsh blog makalesi :
const startObservable = (domNode) => {
var targetNode = domNode;
var observerConfig = {
attributes: true,
childList: true,
characterData: true
};
return new Promise((resolve) => {
var observer = new MutationObserver(function (mutations) {
// For the sake of...observation...let's output the mutation to console to see how this all works
mutations.forEach(function (mutation) {
console.log(mutation.type);
});
resolve(mutations)
});
observer.observe(targetNode, observerConfig);
})
}
Sonra bir generator function
. Bunları henüz kullanmadıysanız, kaçırıyorsunuz - ancak kısa bir özet: bir senkronizasyon işlevi gibi çalışır ve bir yield <Promise>
ifade bulduğunda , vaatin engellenmesi için bekler yerine getirildi ( Jeneratörler bundan daha fazlasını yapıyorlar, ama biz burada ilgileniyoruz ).
// we'll declare our DOM node here, too
let targ = document.querySelector('#domNodeToWatch')
function* getMutation() {
console.log("Starting")
var mutations = yield startObservable(targ)
console.log("done")
}
Jeneratörlerle ilgili zor bir kısım, normal bir işlev gibi 'geri dönmemeleri'. Bu yüzden jeneratörü normal bir fonksiyon gibi kullanabilmek için bir yardımcı fonksiyon kullanacağız. (yine, h / t - dwb )
function runGenerator(g) {
var it = g(), ret;
// asynchronously iterate over generator
(function iterate(val){
ret = it.next( val );
if (!ret.done) {
// poor man's "is it a promise?" test
if ("then" in ret.value) {
// wait on the promise
ret.value.then( iterate );
}
// immediate value: just send right back in
else {
// avoid synchronous recursion
setTimeout( function(){
iterate( ret.value );
}, 0 );
}
}
})();
}
Ardından, beklenen DOM mutasyonu gerçekleşmeden önce herhangi bir noktada çalıştırın runGenerator(getMutation)
.
Artık DOM mutasyonlarını senkronize bir kontrol akışına entegre edebilirsiniz. Ne kadar saçma.