4

I had assumed that I could simply set the onhashchange event handler to null, change the hash, and then set the onhashchange event handler to something, but consider the following code:

window.onhashchange = null;
window.location.hash = "this_should_not_concern_you";
window.onhashchange = function() {alert('chunky bacon')};
doOtherStuff();

So when the has is changed, there's no event handler for hash change, but I still get alerts for "chunky bacon".


Update I chose to go with the setInterval solution from Jed. And although it works (thank you Jed), it's ugly and brittle. If there was a (somewhat paradoxical) onAllEventsHandled event, then I could put my onhashchange subscription in there and be sure that I'm not accidentally alerting "chunky bacon" just because doOtherStuff() takes 2 seconds to complete.

1
  • 1
    +1 for chunky bacon.. just sayin Commented Jun 30, 2011 at 14:30

3 Answers 3

2

It's running asynchronously. Try this:

window.onhashchange = null;
window.location.hash = "this_should_not_concern_you";
setTimeout( function() { window.onhashchange = function() {alert('chunky bacon')};}, 500 );

The 500ms delay gives it enough time to set the handler after the hash is changed. (Even 0ms would probably be enough, though, to stack the events.)

Sign up to request clarification or add additional context in comments.

2 Comments

It's interesting that setting a timeout of 0 is not equivalent to calling the function directly. Good observation!
@AndreiDuma Yes, this is because the timeout method prevents its callback from running in the same event loop. So even 0ms will cause the callback to run in a later event loop.
2

You're code is all part of one event loop and because of that, when the event fires the next loop, your handler is in place. A simplified example of an event loop would be:

  1. Handle Events
  2. Clear call stack
  3. Wait for events (back to step one)

When you change the hash in the same event loop as you're assigning the callback, it isn't processed until the next event loop, which already has it sitting there, waiting for events.

window.location.hash = 'test1';

window.onhashchange = function() {
    console.log(window.location.hash);
};

window.location.hash = 'test2';

This code will log #test2 twice. The handler fires twice, but the value once the handler has fired is test2, both times.

2 Comments

and idea for resolving the issue?
You need to process it after the event has fired, Jed's idea of setting a timeout to push it into the next event loop would work.
0
window.onhashchange = null;

window.location.hash = "this_should_not_concern_you";

window.onhashchange = function() {
    window.onhashchange = function() {alert('chunky bacon')};
};

window.location.hash = "this_should";

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.