Puede desvincular el controlador con .off
, pero hay una advertencia; Si está haciendo esto, solo evite que el manejador se dispare de nuevo mientras se está ejecutando, necesita diferir la reenlace del manejador.
Por ejemplo, considere este código, que utiliza a 5 segundos del sueño caliente para simular algo sincrónico y costoso computacionalmente que se realiza desde dentro del controlador (como la manipulación DOM pesada, por ejemplo):
<button id="foo">Click Me!</div>
<script>
function waitForFiveSeconds() {
var startTime = new Date();
while (new Date() - startTime < 5000) {}
}
$('#foo').click(function handler() {
// BAD CODE, DON'T COPY AND PASTE ME!
$('#foo').off('click');
console.log('Hello, World!');
waitForFiveSeconds();
$('#foo').click(handler);
});
</script>
Este won no funciona Como puede ver si lo prueba en this JSFiddle, si hace clic en el botón mientras el controlador ya se está ejecutando, el controlador ejecutará una segunda vez una vez que finalice la primera ejecución. Además, al menos en Chrome y Firefox, esto sería cierto incluso si no usó jQuery y usó addEventListener
y removeEventListener
para agregar y eliminar el controlador en su lugar. El navegador ejecuta el controlador después del primer clic, desvincula y vuelve a vincular el controlador, y luego maneja el segundo clic y verifica si hay un controlador de clic para ejecutar.
Para evitar esto, es necesario aplazar la reconsolidación del controlador usando setTimeout
, por lo que los clics que se producen mientras el primer controlador está ejecutando serán procesados antes de volver a adjuntar el manejador.
<button id="foo">Click Me!</div>
<script>
function waitForFiveSeconds() {
var startTime = new Date();
while (new Date() - startTime < 5000) {}
}
$('#foo').click(function handler() {
$('#foo').off('click');
console.log('Hello, World!');
waitForFiveSeconds();
// Defer rebinding the handler, so that any clicks that happened while
// it was unbound get processed first.
setTimeout(function() {
$('#foo').click(handler);
}, 0);
});
</script>
Puedes ver esto en acción en this modified JSFiddle.
Naturalmente, esto es innecesario si lo que está haciendo en su controlador ya es asincrónico, ya que entonces ya está cediendo el control al navegador y dejando que elimine todos los eventos de clic antes de volver a vincular su controlador.Por ejemplo, un código como esto va a funcionar bien sin una llamada setTimeout
:
<button id="foo">Save Stuff</div>
<script>
$('#foo').click(function handler() {
$('#foo').off('click');
$.post("/some_api/save_stuff", function() {
$('#foo').click(handler);
});
});
</script>
similar: http://stackoverflow.com/questions/4674991/ intercept-click-event-on-a-button-ask-for-confirmation-then-proceed/4675010 # 4675010 – cregox
3 buenas maneras de hacerlo http://stackoverflow.com/a/1922012/781695 – Medorator