다음을 통해 공유


Timed Update to a Page

One of the features in my ferry app is to show the time remaining until the next ferry.  This simple feature took me on a winding road through AJAX, System.Timers.Timer, Javascript, etc.  It seems like such a simple thing to do, and eventually I hit on the simple approach which is the META tag. 

The requirements are:

1. The default.aspx page can be in one of two states – either the user is logged in, in which case we know what ferry information to display, or they aren’t.

2. If they are logged in, we show the ferry time like this, with the elapsed time from now until the next sailing:

image

3. The elapsed time – from now until the next sailing – should be updated in an efficient manner.

Obviously, the server adds nothing to updating this value – it’s simply the time from “now” to the next sailing.  The only time we need to hit the server is when the elapsed time crosses zero, in which case we need to get the sailing after that on the page. 

My first take was to just use AJAX and use an UpdatePanel and a Timer (client-side in AJAX) to trigger an update.  This worked fine on PCs, but when I hit the page from my Samsung Windows Mobile phone, I got nothing.  I poked around for a while and found it is unclear whether ASP.Net AJAX is supported by the Mobile IE browser with Windows Mobile 6.1.   I figured it might not be based on what I was seeing, so on to plan (B) – let’s just do it server side (yes, it’s not as efficient but…) and so I created a System.Timers.Timer which would simply call my Page Refresh logic every minute.  Worked fine except the page didn’t refresh.  Doing some debugging, I found the timer was triggering – but the page context wasn’t my page, it was some made up page.   Makes sense – the timer is being triggered server side, not client side, so there is no HTTP request.  OK – maybe plain vanilla JavaScript (rather than the fancier AJAX version) might work.  Found a simple piece of code that looks like this:

<script type="text/javascript">
var t;
var timer_is_on = 0;

    function timedCount() {
window.location.reload( true );
t = setTimeout("timedCount()", 60000);
}

    function doTimer() {
if (document.getElementsByName('LoginStatus2')[0].innerText == "Login")
return;
if (!timer_is_on) {
timer_is_on = 1;
timedCount();
}
}
</script>

<body onload="doTimer()">

Seems straightforward – every 60 seconds, if the user is logged in (based on the text of a login control in the page nav bar), refresh the page, updating the elapsed time.  Problem is that the page refresh happens when you enter timedCount – which causes a page load and a call to doTimer.  But because this is a fresh page load, timer_is_on is set to zero – so timer_is_on is set to 1, timedCount is called, which does a window reload – which causes a page load and a call to doTimer.  But because this is a fresh page load, timer_is_on is set to zero – so timer_is_on is set to 1, timedCount is called, which does a windows reload… you get the picture.  Infinite loop.  Arggh!

For the release of this I need to do tomorrow, I’ve decided to bail on the page refresh.   But I have an idea of one thing to try which I found on this blog.

But the really right way to do this is to have Javascript on the client side figure out the elapsed time and update just that control.  If the browser doesn’t support that (as I’m suspecting IE Mobile doesn’t), then you don’t get the auto refresh.  That will my approach next week when I come back to this.  In the meantime, got to get this release out!