我正在使用proxy object
来检测对象值的变化,然后通过AJAX加载新内容,我使用setInterval
函数来等待直到AJAX请求中的元素存在,然后执行一段代码。我这样做是因为我的情况需要这样做。我做了一个简短的示例:
var handler = {
makeThings: 0,
otherStuff: 0
};
var globalHandler = new Proxy(handler, {
set: function(obj, prop, value) {
obj[prop] = value
if (prop == "makeThings") {
var clearTimeSearchProxy = setInterval(function() {
if ($("p").length) {
console.log("The element finally exist and we execute code");
clearTimeout(clearTimeSearchProxy);
}
}, 100);
}
return true;
}
});
$(document).ready(function() {
$("button").on("click", function() {
globalHandler.makeThings = 1;
//This element comes with ajax but I use a setTimeout for this example
setTimeout(function() {
$("#newContent").append("<p>Ajax element</p>");
}, 2000);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<button>New content</button>
<div id="newContent"></div>
</body>
现在,我想知道如何以一种更干净,有效和优雅的方式改进代码。当通过AJAX来的元素存在于promises
中时,我正在考虑使用setInterval
而不是DOM
来执行代码。
我如何使其起作用?在这种情况下,我应该使用其他JavaScript功能代替promises
吗?我信守实现我所需要的承诺,这是我到目前为止已经尝试过的。
var handler = {
makeThings: 0,
otherStuff: 0
};
var globalHandler = new Proxy(handler, {
set: function(obj, prop, value) {
obj[prop] = value
if (prop == "makeThings") {
var myFirstPromise = new Promise((resolve, reject) => {
if ($("p").length) {
resolve("Exist");
} else {
reject("It doesnt exist.");
}
});
myFirstPromise.then((data) => {
console.log("Done " + data);
}).catch((reason) => {
console.log("Handle rejected promise: " + reason);
});
}
return true;
}
});
$(document).ready(function() {
$("button").on("click", function() {
globalHandler.makeThings = 1;
//This element comes with ajax but I use a setTimeout for this example
setTimeout(function() {
$("#newContent").append("<p>Ajax element</p>");
}, 2000);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<button>New content</button>
<div id="newContent"></div>
</body>
答案 0 :(得分:2)
请勿 等待 。而是订阅目标元素更改的通知。
用于监听DOM树中的更改的API是MutationObserver。
MutationObserver接口提供了监视对DOM树所做的更改的功能。它旨在替代DOM3事件规范中较早的“突变事件”功能。
使用它来观察元素的变化,如下所示:
// You selected `$("p")` in your snippet, suggesting you're watching for the inclusion of 'any' `p` element.
// Therefore we'll watch the `body` element in this example
const targetNode = document.body;
// Options for the observer (which mutations to observe)
const config = {
attributes: false,
characterData: false,
childList: true,
subtree: true
};
// Callback function to execute when mutations are observed
const callback = function(mutationsList, observer) {
for(let mutation of mutationsList) {
if ( mutation.type === "childList" ) {
continue;
}
const addedNodes = Array.from( mutation.addedNodes) ;
if ( addedNodes && addedNodes.some( node => node.nodeName === "P" ) ) {
observer.disconnect();
console.log("The element finally exist and we execute code");
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
答案 1 :(得分:2)
我终于用MutationObserver interface
而不是promises
轻松实现了。
var handler = {
makeThings: 0,
otherStuff: 0
};
var globalHandler = new Proxy(handler, {
set: function(obj, prop, value) {
obj[prop] = value
if (prop == "makeThings") {
var observer = new MutationObserver(function(mutations) {
if ($("p").length) {
console.log("Exist, lets do something");
observer.disconnect();
}
});
// start observing
observer.observe(document.body, {
childList: true,
subtree: true
});
}
return true;
}
});
$(document).ready(function() {
$("button").on("click", function() {
$("p").remove();
globalHandler.makeThings = 1;
//This element comes with ajax but I use a setTimeout for this example
setTimeout(function() {
$("#newContent").append("<p>Ajax element</p>");
}, 2000);
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<button>New content</button>
<div id="newContent"></div>
</body>
答案 2 :(得分:0)
rxjs可以大大简化您要尝试做的事情。一个非常基本的实现,仅使用主题和订阅:
const {
Subject
} = rxjs;
const sub = new Subject();
sub.subscribe(e => {
console.log(`received data ${e}`);
// do your thing
});
// simulate something async
setTimeout(() => {
sub.next('foo');
}, 1000);
<script src="https://unpkg.com/rxjs@6.5.2/bundles/rxjs.umd.min.js"></script>