DOM event precedence
This was not, so far as i know, explicitly defined in the past. Different browsers are free to implement event ordering however they see fit. While most are close enough for all practical purposes, there have been and continue to be some odd edge cases where browsers differ somewhat (and, of course, the many more cases where certain browsers fail to send certain events at all).
That said, the HTML 5 draft recommendation does make an attempt to specify how events will be queued and dispatched - the event loop:
To coordinate events, user
interaction, scripts, rendering,
networking, and so forth, user agents
must use event loops as described in
this section.There must be at least one event loop
per user agent, and at most one event
loop per unit of related
similar-origin browsing contexts.An event loop has one or more task
queues. A task queue is an ordered
list of tasks [...]
When a user agent is to queue a task,
it must add the given task to one of
the task queues of the relevant event
loop. All the tasks from one
particular task source must always be
added to the same task queue, but
tasks from different task sources may
be placed in different task queues.
[...][...]a user agent could have one task queue
for mouse and key events (the user
interaction task source), and another
for everything else. The user agent
could then give keyboard and mouse
events preference over other tasks
three quarters of the time, keeping
the interface responsive but not
starving other task queues, and never
processing events from any one task
source out of order. [...]
Note that last bit: it is up to the browser implementation to determine which events will be grouped together and processed in order, as well as the priority given to any particular type of event. Therefore, there's little reason to expect all browsers to dispatch all events in a fixed order, now or in the future.
Are event handlers in JavaScript called in order?
This has been changed with DOM3! While the DOM level 2 events specification did state
When the event reaches the target, any event listeners registered on the
EventTarget
are triggered. Although allEventListeners
on theEventTarget
are guaranteed to be triggered by any event which
is received by thatEventTarget
, no specification is made as to the
order in which they will receive the event with regards to the otherEventListeners
on theEventTarget
.
The current DOM level 3 events specification does now state
The implementation MUST determine the current target's candidate
event listeners.
This MUST be the list of all event listeners that have been registered
on the current target in their order of registration.HTML5
defines the ordering of listeners registered through event handler
attributes.
[…]Finally, the implementation MUST process all candidate event
handlers
in order […]
However, I can't find a reference to this behaviour in the DOM 4 draft any more.
How to change event execution order?
Please review this one:
<!DOCTYPE html><html>
<head> <meta charset="utf-8"> <title>Close window</title></head>
<body> <!-- here is your first AddEventlistener--> <button id="abc" onclick="temp1()">button</button>
<script type="text/javascript"> function temp1() { alert("temp1"); };
function temp2() { alert("temp2"); }
/*then here is your second AddEventlistener*/ var d = document.getElementById("abc"); d.addEventListener("click", temp2, false);
/*javascript will execute it in order if you want to change the order. remove first EventListener then register new one after. something like this: */ //remove listener d.onclick = null; //register new d.addEventListener('click', temp1); </script></body>
</html>
Order of execution of functions bound to an event in Javascript
Event handlers are always called in the order in which they were registered.
Once registered, you cannot insert additional handlers ahead of them[*].
[*] unless you are some how able to obtain a list of all the handlers, and their EventListener
objects, and call removeEventListener
to remove them, insert your own, and then reinsert the originals. In practise this is likely to be impossible.
DOM event precedence
This was not, so far as i know, explicitly defined in the past. Different browsers are free to implement event ordering however they see fit. While most are close enough for all practical purposes, there have been and continue to be some odd edge cases where browsers differ somewhat (and, of course, the many more cases where certain browsers fail to send certain events at all).
That said, the HTML 5 draft recommendation does make an attempt to specify how events will be queued and dispatched - the event loop:
To coordinate events, user
interaction, scripts, rendering,
networking, and so forth, user agents
must use event loops as described in
this section.There must be at least one event loop
per user agent, and at most one event
loop per unit of related
similar-origin browsing contexts.An event loop has one or more task
queues. A task queue is an ordered
list of tasks [...]
When a user agent is to queue a task,
it must add the given task to one of
the task queues of the relevant event
loop. All the tasks from one
particular task source must always be
added to the same task queue, but
tasks from different task sources may
be placed in different task queues.
[...][...]a user agent could have one task queue
for mouse and key events (the user
interaction task source), and another
for everything else. The user agent
could then give keyboard and mouse
events preference over other tasks
three quarters of the time, keeping
the interface responsive but not
starving other task queues, and never
processing events from any one task
source out of order. [...]
Note that last bit: it is up to the browser implementation to determine which events will be grouped together and processed in order, as well as the priority given to any particular type of event. Therefore, there's little reason to expect all browsers to dispatch all events in a fixed order, now or in the future.
Event Handling order
Events bubble "up" the DOM tree, so if you've got handlers for an element and its parent, the child element handler will be called first.
If you register more than one handler for an event on a single DOM element (like, more than one "click" handler for a single button), then the handlers are called in the order that they were attached to the element.
Your handlers can do a few things to change what happens after they're done:
- With the passed-in event parameter, call
event.preventDefault()
to keep any "native" action from happening - call
event.stopPropagation()
to keep the event from bubbling up the DOM tree - return false from the handler, to both stop propagation and prevent default
Note that for some input elements (checkboxes, radio buttons), the handling is a little weird. When your handler is called, the browser will have already set the checkbox "checked" value to the opposite of its former value. That is, if you have a checkbox that is not checked, then a "click" handler will notice that the "checked" attribute will be set to "true" when it is called (after the user clicks). However, if the handler returns false, the checkbox value will actually NOT be changed by the click, and it will remain un-checked. So it's like the browser does half of the "native" action (toggling the element "checked" attribute) before calling the handler, but then only really updates the element if the handler does not return false (or call "preventDefault()" on the event object).
Execution order between React's useEffect and DOM event handler
I discussed the problem with my colleague and finally found a solution. He pointed out that new React Fiber engine should not ensure the order of execution of side-effects, and suggested adding a revision number to the state.
Here is an example. The incremented revision
will always invoke useEffect
even if the set value
is not changed. Subscribers obtain state.value
from Provider
and don't need to concern about the underlying revision
.
import React, { useCallback, useEffect, useReducer, useRef } from 'react';
const storageKey = 'name';
const defaultValue = 'John Doe';
const orDefault(value) = (value) =>
(typeof value !== 'undefined' && value !== null) ? value : defaultValue;
const initializer = (arg) => ({
value: orDefault(localStorage.getItem(storageKey)),
revision: 0,
});
const reducer = (state, newValue) => ({
value: newValue,
revision: state.revision + 1,
});
const useCachedValue = () => {
const [state, setState] = useReducer(reducer, null, initializer);
const initialized = useRef(false);
// save the updated value as a side-effect
useEffect(() => {
if (initialized.current) {
localStorage.setItem(storageKey, state.value);
} else {
// skip saving just after the (re-)initialization
initialized.current = true;
}
}, [state]);
// re-initialize when the storage has been modified by another window
const handleStorageEvent = useCallback((e) => {
if (e.key === null || e.key === storageKey) {
initialized.current = false;
setState(orDefault(e.newValue));
}
}, []);
useEffect(() => {
if (typeof window !== 'undefined') {
window.addEventListener('storage', handleStorageEvent);
return () => {
window.removeEventListener('storage', handleStorageEvent);
};
}
}, []);
return [state.value, setState];
};
const Context = React.createContext();
const Provider = (props) => {
const cachedValue = useCachedValue();
return (
<Context.Provider value={cachedValue}>
{props.children}
</Context.Provider>
);
};
The Order of Multiple Event Listeners
Prototype relies on the browser's underlying firing mechanism for order (not all libraries do, see below). The order in which event handlers are fired was not guaranteed by the DOM events stuff originally. From the DOM2 Events specification:
Although all
EventListeners
on theEventTarget
are guaranteed to be triggered by any event which is received by thatEventTarget
, no specification is made as to the order in which they will receive the event with regards to the otherEventListeners
on theEventTarget
.
The vast majority of browser implementations (Chrome, Firefox, Opera, etc.), including IE9, fire the handlers in the order in which they were attached. IE8 and earlier do it the other way around.
The newer DOM3 event spec, still a work in progress, introduces the requirement that they be fired in order of registration (what most browsers do):
Next, the implementation must determine the current target's candidate event listeners. This must be the list of all event listeners that have been registered on the current target in their order of registration.
...which is probably part of why IE9 does that now (IE9 markedly improved Microsoft's support for the events standards, adding addEventListener
, etc.).
Some JavaScript libraries (jQuery for instance) do guarantee the order regardless of the browser, by attaching only a single handler per event per element and maintaining their own list of user code handlers to fire.
Related Topics
How to Load Local Script Files as Fallback in Cases Where Cdn Are Blocked/Unavailable
Merge JavaScript Objects in Array with Same Key
How to Decide When to Use Node.Js
How to Use Redirect in Version 5 of React-Router-Dom of Reactjs
Overloading Arithmetic Operators in JavaScript
iPad Web App: Detect Virtual Keyboard Using JavaScript in Safari
Merge Multiple Objects Inside the Same Array into One Object
Convert a Binary Nodejs Buffer to JavaScript Arraybuffer
Does Never Resolved Promise Cause Memory Leak
Why Does !New Boolean(False) Equals False in JavaScript
Safari 3Rd Party Cookie Iframe Trick No Longer Working
How to Toggle an Element's Class in Pure JavaScript
How to Guarantee That My Enums Definition Doesn't Change in JavaScript
How to Execute Promises Sequentially, Passing the Parameters from an Array
Remove Not Alphanumeric Characters from String
Difference Between Using Bracket ('[]') and Dot ('.') Notation
How to Get Notified About Changes of the History via History.Pushstate