我有一个用例,我想监视添加的事件侦听器。我在这里找到了一种对我有用的方法:https://stackoverflow.com/a/6434924
这段代码似乎在很多情况下都有效,但是,当在包含 React 应用程序的页面上使用时,它似乎会抛出
InternalError: too much recursion
异常。
最简单的再现器如下所示:
Node.prototype.realAddEventListener = Node.prototype.addEventListener;
Node.prototype.addEventListener = function(a,b,c){
this.realAddEventListener(a,b,c);
}
在错误发生之前打印 this
、
a
和
b
会产生:
this = [object HTMLUnknownElement]
a = react-invokeguardedcallback
b = function callCallback() {
// We immediately remove the callback from event listeners so that
// nested `invokeGuardedCallback` calls do not clash. Otherwise, a
// nested call would trigger the fake event handlers of any call higher
// in the stack.
fakeNode.removeEventListener(evtType, callCallback, false); // We check for window.hasOwnProperty('event') to prevent the
// window.event assignment in both IE <= 10 as they throw an error
// "Member not found" in strict mode, and in Firefox which does not
// support window.event.
if (typeof window.event !== 'undefined' && window.hasOwnProperty('event')) {
window.event = windowEvent;
}
func.apply(context, funcArgs);
didError = false;
}
使用上面的函数处理程序向 react-invokeguardedcallback
上的 HTMLUnknownElement 添加侦听器会导致我被劫持的
addEventListener
递归吗?
事实证明
realAddEventListener
并未分配给原始
addEventListener
实现。相反,我对 addEventListener 的重新分配首先发生,然后
realAddEventListener
被分配给我被劫持的函数,导致无限递归。修复方法是通过 Promises 确保事件的顺序:
const handlerMagic = new Promise((resolve)=>{
Node.prototype.realAddEventListener = Node.prototype.addEventListener;
resolve()
}).then(_=>{
Node.prototype.addEventListener = function(a,b,c){
this.realAddEventListener(a,b,c)
}
})
现在工作正常。