vue-on-click-outside
vue-on-click-outside copied to clipboard
Race condition with setTimeout
I have two elements on a page that each have an on-click-outsite set (two date pickers), say dp1 and dp2. I am consistently able to produce a race condition where i open dp1, open dp2 (which closes dp1), open dp1 again (closing dp2), and open dp2 again, but dp1 one does not close. The problem is that the setTimeout runs in the next tick, which allows the deregistration of a handler to destroy the dom listener, such that the handler that is then registered is never called.
The simple (naive?) fix is to just remove the setTimeout and run the handler registration immediately. (I'm not sure of the use case that the setTimeout addresses.)
If the setTimeout is required, the fix is to move the code that creates the dom listener inside the setTimeout callback.
Both of these fixes are trivial, and if there is a preference i can provide a PR.
Bump. Got burned by the same issue, although I had to investigate it myself to recognize what it was.
To speculate on the answer to your question @mlohbihler, I think the settimeout might be there as a precaution in case something isn't fully loaded on the DOM when the bind hook is executed. I don't know exactly what that would be though.
If it helps at all, this is what the function would look like using fix 2:
function bind(el, binding) {
var callback = binding.value,
modifiers = binding.modifiers;
// unbind any existing listeners first
unbind(el);
setTimeout(function () {
if (!domListener) {
domListener = on(document.documentElement, 'click', function (event) {
registeredHandlers.forEach(function (handler) {
return handler.check(event);
});
});
}
registeredHandlers.push(modifiers.static ? staticStrategy(el, callback) : dynamicStrategy(el, callback));
}, 0);
}