Why does `alert("2nd");` execute before `window.history.back();`? - javascript

When I ran the following two JavaScript commands...
> window.history.back(); alert("2nd");
...I was expecting the window to go to the previous page, and then display the alert. What happens is "2nd" actually pops up first, and then the window goes back. If I reverse them like this...
> alert("2nd"); window.history.back();
...the commands still execute in the same order. What don't I understand about JavaScript control flow? How would I get window.history.back(); to run first?

Well, it makes sense that the alert is not displayed after the other page has loaded. The script is part of the loaded page, so if that would work, it would mean you could inject javascript in the previous page, which is of course undesirable.
So as I see it, there are 3 possibilities:
The back function is blocking and works immediately, navigating to a previous page, and terminate the running script. This obviously isn't happening, otherwise you wouldn't get the alert at all.
The back function works immediately, but the script is only terminated when the browser has enough information to start loading the other document. This doesn't seem to be the case. If it were, the browser would probably load the document in the background while the alert is open, but that doesn't happen.
The back function just signals the browser to go back, and the script keeps running until it's idle before that request is actually fulfilled. This seems to be the case. Navigation only starts when the alert is closed and the script ends. (At least in Chrome).
Anyway, if you want this to work, you'll have to call alert from the page you are navigating to.

Control has to be given back to the browser before back is actually executed. It just tells the page when you get a chance, go back.
Once control is return the browser unloading hooks are called (onbeforeunload, onunload, browser specific events).

Related

Why would a screen, while still loading, wait before redirecting to a new screen if a user has already clicked a link to that new screen

I have a screen that loads a lot of data from the Server while it loads, it also has some JS running of course. Early the page loading process, a link becomes available for the user that they can click and it will take them to a different screen. I would expect that as they click the link it would immediately redirect them to the new screen. However, after they click it, it seems to wait for some of the data fetches from the server to rust before navigating to that new screen - either this or it is waiting for JS to finish perhaps - I am unsure of the reason for the delay - and this is the question: what is causing this delay (it is definately related to the screen still loading) and is there a way I can force the redirect to happen immediately.
Thanks
Since it is basic functionality I have not been able to try anything but to look in the Dev Tools to see what is happening with the network calls - which is seems to wait for a few to come back before redirecting.

How do I run additional JS function after calling location.reload()?

I am trying to run some code that refreshes the webpage, and THEN does the console log.
The issue is the console.log is happening before the page reload.
location.reload();
console.log("test");
How do I adjust this to get the desired behavior?
The very act of refreshing a web page ends execution of scripts on that page, apart from what might be called in onbeforeunload or onunload handlers. Once the reload has actually occurred, no more JavaScript in the pre-reload page can be executed.
If you need to cause something to happen after content has been reloaded, you'll have to use something like a cookie to pass a message to the reloaded page indicating the action you want to take.
Use extentions like TamperMonkey to handle your script.

Stopping JavaScript code execution immediately after a redirect in Chrome DevTools

I've got a scenario where a user receives a round-trip redirect via query string from one site to another.
For instance, the user starts on example-site-a.com, gets redirected to example-site-b.com?redirectBackTo=example-site-a.com, and is redirected back to the original site by setting the window.location.href to the query string value.
I would like to debug/step through JavaScript located on the second site, but the second redirect happens in the blink of an eye.
Say my JavaScript on example-site-b.com looks like this:
<script>
alert("debug!");
debugger;
console.log("test");
</script>
alert() doesn't pause the code execution and debugger isn't working either. I also tried setting an Event Listener Breakpoint in Chrome DevTools to pause on Script First Statement, but the console.log statement is still eluding me.
I'm just looking to step through the above code on example-site-b. Any ideas?
alex said that this suggestion from Shilly did the trick:
What is causing this redirect? WIll it wait for all JS to have stopped running? In that case you can use a setTimeout so you have time to press the F12 button. If the redirect will happen serverside or will not wait for JS in site-b to finish, you'll have to remove the redirect mechanism for a bit and just do a manual redirect to site-b to test.

Chrome AJAX on page-load causes "busy cursor" to remain

In Google Chrome, AJAX called within $(function(){....}); seems to keep the page loading.
I have a site with a few pages with tabs. Because I'm using cheap godaddy hosting, I want the page to load as fast as possible. I thus want to load a page on 1 tab and then in the background use AJAX to load the other tabs. When I run AJAX from
$(function(){
/*AJAX CODE HERE */
});
The cursor shows the page as loading for a long time (http://jsfiddle.net/mazlix/7fDYE/9/)
I have figured out a way (in chrome atleast) to somewhat fix that using setTimeout(); (http://jsfiddle.net/mazlix/7fDYE/8/), but this only works if you correctly predict when the window finishes fully loading and obviously makes it take longer to load. I want a way to load content via AJAX immediately after the page loads, so no "busy-cursor" is displayed while waiting for the returned AJAX.
Google Chrome shows Loading Indicator as long as there are no new queries to servers. While the loading indicator is shown, all new requests are causing Chrome to extend the time the indicator is shown. Furthermore, when esc is pressed while the indicator is shown, all requests are aborted! These include AJAX requests and even Flash requests! Take a look at this question: i thought it was because of Youtube, but it turned to be Chrome's usual behavior.
The only way to avoid "extending" the time Loading indicator is shown, is making the requests after the loading indicator is hidden: i.e. when all queries to server are completed. JQuery's documentation on .load() says:
The load event is sent to an element when it and all sub-elements have been completely loaded. This event can be sent to any element associated with a URL: images, scripts, frames, iframes, and the window object.
So, if you're sure that there are only images, scripts and frames on your page, window.load() will be fired just when you need it. Adding setTimeout() to it will work as you like. Here is an example: http://jsfiddle.net/7fDYE/22/
If there are other requests being made before your request, you should wait for them to be completed! For example, you know that besides the images/scripts etc. you have 3 more AJAX requests before the page loads. You can have something like this:
var loaded=0,needsToBeLoaded=4; //3 AJAX + window
function onLoad(){
loaded++;
if(loaded==needsToBeLoaded){
//do the AJAX request
}
}
window.load(onLoad);
// add onLoad() to all 3 AJAX request handlers
I'm not sure what you can do with Flash requests...
Update
This solution will not work for Chrome. It stops the loading indicator only when all requests made before window load have completed. The only solution appears to be to get it to make the request after window load, but as far as I know, this is only possible with setTimeout, which isn't great.
Update
To get around the pointer issue in Chrome, you could set the cursor style as shown in this fiddle. It's a bit hacky and it doesn't address the issue of the loading indicator at the top of the tab.
The loading indicator will be present in browsers until the page has loaded (window's load event). In $(function(){someCode();});, someCode is executed when the DOM load event is triggered (when all content has been parsed and inserted into the DOM, before page load). The execution of JavaScript at this point blocks the window's load event from firing, and so prevents the loading indicator from stopping. Note that image loading also blocks the window's load event.
Instead, you could try $(window).load(function(){someCode();});. In this example, someCode is executed when the window's load event is triggered. This is at the point where the browser's loading indicator stops.
So, instead of:
$(function(){
/*AJAX CODE HERE */
});
Try:
$(window).load(function(){
/*AJAX CODE HERE */
});
Note that this may cause your JavaScript to begin execution later, which may not be desirable.
There is a super simple, fool proof solution to this:
Wrap your function in a setTimeout call, and use an interval of 0. This will queue the function to be called immediately, but Chrome will no longer wait for it to load before considering the page 'complete'. You do NOT need to make any guesses about when the page will be complete, just make sure you're calling setTimeout inside the jquery Ready handler, like so:
$(window).load(function() {
setTimeout(function() {
$("#result").html(ajax_load);
$.post("/echo/json/", {json: json1, delay: 10000}, show_json, "json");
}, 0);
});
According to JQuery docs, no javascript should be run till ready for example
$(document).ready(function() {someCode();});
with that in mind i changed your jsFiddle (it takes some time to load but it works)
Edit: hadnt forked jsfiddle ><
I'm not sure I agree that this is a problem. I'd say this is a desirable behavior from chrome as it indicates that it's in fact not finished loading. I would say that Firefox is actually incorrect about not indicating that it's still waiting for a script callback to finish.
This could be a matter of personal taste (I like the browser to indicate that it's waiting/working, even if it makes my browser seem slow), in which case succeeding in "fixing" this "problem", will make the browser not behave in the way the user is used to. In web development you really should not try to force the browser to behave in a specific way that is not essential to how the webapp works, because you're likely to end up enforcing a look-and-feel from one os you're used to into another os with a different feel, making it feel more foreign to the users of another os (even if it makes the site feel more native to you).
The busy cursor is not a problem anyway, because elements already loaded, are still responsive.
Looks like this is a Chrome issue and they are not fixing it:
https://bugs.chromium.org/p/chromium/issues/detail?id=26723

does a chrome extension content script get stopped if it takes too long to finish?

I have a content script running on every page. It updates the html of the page, which seems to take more time on longer pages (the script walks the DOM a lot of times). On longer pages the script could take up to 10-20 seconds to finish, and it seems that when it takes too long chrome stops the script, because on these pages I see only a part of the page changed.
The weird part is that when I add several alerts somewhere in the code, dividing the runtime to several parts, the script runs perfectly fine and changes the entire page. However when the alert is removed, the script is again stopped prematurely, and only a part of the page gets changed.
My only conclusion is that chrome stops scripts that run too long, so my question is - is that true? And if so - what can be done about it? (besides using annoying pop-up alerts)
I have another theory, the script stops because somehow there is a conflict when simultaneous commands try to change the DOM. Does this make more sense?
More details about the architecture: The background page gets a message from the content script. This message includes a callback function (the function that actually changes the HTML). This function is then called from the background page several times, relative to the length of the page. If I insert an alert inside the callback function, every call is run without problems. If however I remove it, only the first call from the background page is made, and further calls don't do anything (although the background page code keeps running).
Yes, and usually it prompts the user if he/she wants to continue waiting or to kill the page.
Chrome has some limits in place if the JavaScript takes a long time (hence blocks the main thread) it will notify you about taking too much time.
You have two options:
Can you offload some processing to a HTML5 worker and post a message back to the page when processing is complete?
Can you offload some processing to the background page and send a message request back to the content script when processing is complete?
I found out what was the problem. I was using the callback given by the message from the content script to the background html page. This callback can be run only once, because there is only one response allowed for each message send to the background page.
Some sort of bug in chrome causes many responses to work when I added an alert inside the callback function.
The problem was solved by breaking down the content of the message into several messages.

Categories

Resources