是否可以让其他 javascript 事件侦听器等待异步事件?
Is it possible to make other javascript event listeners wait for an async event?
我想劫持一个网页(使用 Tampermonkey),它有一个带有一些事件侦听器的按钮,最后是一个重定向。
有没有办法将我自己的点击事件处理程序添加到按钮,这会发出 AJAX 请求,并等待它完成,然后再继续处理其他事件侦听器,所以我的 AJAX 请求在重定向之前确定已完成?
我知道 stopImmediatePropagation 但不知道如何 "delay" 异步传播。
不,您不能让其他事件处理程序等待。您 有时 可以 overwrite/hijack 现有功能,但这通常无法使用 Tampermonkey,并且可能会变得混乱(例如在 Firefox + Greasemonkey 中)。
对于像按钮这样的可点击元素,一种解决方法是覆盖按钮,在其上设置侦听器,然后在时机成熟时让它们在原始按钮上触发所需的事件.
例如,请考虑以下代码段:
#mainButton
及其代码代表原始页面。
- "Hijack" 按钮模拟 Tampermonkey 脚本的 运行。
- "script" 创建一个与按钮大小相同的 div 并将其放置在按钮上方。因此,任何点击都会被 div 而不是按钮捕获。
- 拦截代码执行一些异步操作,然后触发对原始按钮的点击。
//--------------------------
//--- The page's code:
//--------------------------
$("#mainButton").click ( function () {
logline ("The button was clicked.");
} );
//------------------------------
//--- The script setup and code:
//------------------------------
$("#tmIntercept").click ( function () {
logline ("==> Main button is now intercepted.");
//this.disabled = true;
$(this).attr ( {"disabled": true} );
var targBtn = $("#mainButton");
var overlayDiv = $('<div id="tmBtnOverlay">').css ( {
'width': targBtn.outerWidth (),
'height': targBtn.outerHeight (),
'position': 'absolute',
'top': targBtn.offset ().top,
'left': targBtn.offset ().left,
'z-index': 8888,
'background': "lime",
'opacity': "0.2"
} )
.appendTo ("body");
overlayDiv.click ( function (zEvent) {
//-- Guard against more global handlers.
zEvent.stopImmediatePropagation ();
logline ("Doing some AJAXy thing... <span> </span>");
//-- Simulated AJAX call:
setTimeout (doSomeAjaxyThing, 1111);
} );
} );
function doSomeAjaxyThing () {
$("#eventLog > p > span").first ().text ('Done.');
//-- Now send required events to the original button:
var clickEvent = document.createEvent ('MouseEvents');
clickEvent.initEvent ("click", true, true);
$("#mainButton")[0].dispatchEvent (clickEvent);
}
function logline (str) {
this.lineNumber = this.lineNumber + 1 || 1;
var lineDisplay = (1e15 + this.lineNumber + "").slice (-3); //-- zero pad 3 places
$("#eventLog").prepend ('<p>' + lineDisplay + ' ' + str + '</p>');
}
#mainButton {
font-size: 2em;
padding: 0.3ex 2ex;
}
#eventLog {
max-height: 50vh;
overflow-y: auto;
overflow-x: hidden;
}
#eventLog > p {
margin: 0.3ex 2ex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<p><button id="mainButton">The Button</button></p>
<p><button id="tmIntercept" autocomplete="off">Hijack the button</button></p>
<fieldset>
<legend>Event Log:</legend>
<div id="eventLog"></div>
</fieldset>
备注:
- 在某些情况下,您可能会想直接调用页面的代码。但触发事件通常要简单得多、健壮且安全。
- 这只是叠加过程的一个演示。实际上,简单的绝对定位可能需要调整。 (通常将目标节点包裹在相对定位的div中并调整偏移量。)这超出了本题的范围。
我想劫持一个网页(使用 Tampermonkey),它有一个带有一些事件侦听器的按钮,最后是一个重定向。
有没有办法将我自己的点击事件处理程序添加到按钮,这会发出 AJAX 请求,并等待它完成,然后再继续处理其他事件侦听器,所以我的 AJAX 请求在重定向之前确定已完成?
我知道 stopImmediatePropagation 但不知道如何 "delay" 异步传播。
不,您不能让其他事件处理程序等待。您 有时 可以 overwrite/hijack 现有功能,但这通常无法使用 Tampermonkey,并且可能会变得混乱(例如在 Firefox + Greasemonkey 中)。
对于像按钮这样的可点击元素,一种解决方法是覆盖按钮,在其上设置侦听器,然后在时机成熟时让它们在原始按钮上触发所需的事件.
例如,请考虑以下代码段:
#mainButton
及其代码代表原始页面。- "Hijack" 按钮模拟 Tampermonkey 脚本的 运行。
- "script" 创建一个与按钮大小相同的 div 并将其放置在按钮上方。因此,任何点击都会被 div 而不是按钮捕获。
- 拦截代码执行一些异步操作,然后触发对原始按钮的点击。
//--------------------------
//--- The page's code:
//--------------------------
$("#mainButton").click ( function () {
logline ("The button was clicked.");
} );
//------------------------------
//--- The script setup and code:
//------------------------------
$("#tmIntercept").click ( function () {
logline ("==> Main button is now intercepted.");
//this.disabled = true;
$(this).attr ( {"disabled": true} );
var targBtn = $("#mainButton");
var overlayDiv = $('<div id="tmBtnOverlay">').css ( {
'width': targBtn.outerWidth (),
'height': targBtn.outerHeight (),
'position': 'absolute',
'top': targBtn.offset ().top,
'left': targBtn.offset ().left,
'z-index': 8888,
'background': "lime",
'opacity': "0.2"
} )
.appendTo ("body");
overlayDiv.click ( function (zEvent) {
//-- Guard against more global handlers.
zEvent.stopImmediatePropagation ();
logline ("Doing some AJAXy thing... <span> </span>");
//-- Simulated AJAX call:
setTimeout (doSomeAjaxyThing, 1111);
} );
} );
function doSomeAjaxyThing () {
$("#eventLog > p > span").first ().text ('Done.');
//-- Now send required events to the original button:
var clickEvent = document.createEvent ('MouseEvents');
clickEvent.initEvent ("click", true, true);
$("#mainButton")[0].dispatchEvent (clickEvent);
}
function logline (str) {
this.lineNumber = this.lineNumber + 1 || 1;
var lineDisplay = (1e15 + this.lineNumber + "").slice (-3); //-- zero pad 3 places
$("#eventLog").prepend ('<p>' + lineDisplay + ' ' + str + '</p>');
}
#mainButton {
font-size: 2em;
padding: 0.3ex 2ex;
}
#eventLog {
max-height: 50vh;
overflow-y: auto;
overflow-x: hidden;
}
#eventLog > p {
margin: 0.3ex 2ex;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<p><button id="mainButton">The Button</button></p>
<p><button id="tmIntercept" autocomplete="off">Hijack the button</button></p>
<fieldset>
<legend>Event Log:</legend>
<div id="eventLog"></div>
</fieldset>
备注:
- 在某些情况下,您可能会想直接调用页面的代码。但触发事件通常要简单得多、健壮且安全。
- 这只是叠加过程的一个演示。实际上,简单的绝对定位可能需要调整。 (通常将目标节点包裹在相对定位的div中并调整偏移量。)这超出了本题的范围。