I'm developing an web application using asp.net mvc, and i need to do a stopwatch (chronometer) (with 30 seconds preprogrammed to start in a certain moment) on client-side using the time of the server, by the way, the client's clock can't be as the server's clock. So, i'm using Jquery to call the server by JSon and get the time, but it's very stress because each one second I call the server to get time, something like this:
$(function() {
GetTimeByServer();
});
function GetTimeByServer() {
$.getJSon('/Home/Time', null, function(result) {
if (result.SecondsPending < 30) {
// call another function to start an chronometer
} else {
window.SetTimeout(GetTimeByServer, 1000); //call again each 1 second!
}
});
}
It works fine, but when I have more than 3 or 4 call like this, the browser slowly but works! I'd like to know, how improve more performace in client side, or if is there any way to do this... is there any way to client listen the server like a "socket" to know if the chronometer should start...
PS: Sorry for my english!
thanks
Cheers
Felipe,
On page load get the server time and also the Client Side time. and use the two in reference to determine what the server time is on the server side without using AJAX call every time. Sorry for the excess of suedo code but it shouldnt be too hard.
var ServerTimeReference;
var ClientTimeReference;
function InitializeTime()
$.getJSon('/Home/Time', null, function (result) {
ServerTimeReference = result.ServerTime; //convert to js time
ClientTimeReference = new Date();
});
function GetServerTime() {
var TimeDifference = //get the difference between server and Client time
var CurrentClientDateTime = new Date();
var CurrentServerTime = // using timedifference and CurrentClientDateTime calculate ServerTime
return CurrentServerTime;
}
I would do all of the time checking on the client side. You are already using jQuery, just use a timer plugin. I've had good success with this one.
If you really want to use it like this, you basically got this options:
Use AJAX polling (COMET)
Use HTML5 WebSockets
I don't fully understand why you just send a value to the client and not just a "GO" string if the client should start doing anything.
Either way, you don't have to poll that every second (I mean come on, if your local PC's clock is THAT wrong would be a bad sign). So it should be enough to 'syncronize' every 10 seconds for instance (which also is pretty fast).
So my basic strategy would be, call a backend function which tells my client, how much time is left to go and setup a setTimeout on that value.
Related
I'm working on a small project, that combines Java(servlets) with some web elements. I've got a Java back-end that deals with registration and login. When the user has logged in, he/she arrives at the dashboard where a timer awaits them.
The timer should be set at 25 minutes and when the user presses 'start', it should start counting down to zero. When zero has been reached, I want the timer to save the timestamps (begin/end) to MySQL and automatically start a 5 minute timer.
I've been looking on Google for quite some time. jQuery seems the easiest option, but I'm genuinely struggling getting this started.
Is there anyone who could help me?
Perhaps guide me on the right path or (if you have time) have a little coding session?
On waiting page use Javascript:
var timeleft = 1500; // seconds left
var timer = setInterval(function () {
timeleft--;
// optional: update HTML element here
if (timeleft == 0) { saveTimestamp(); clearInterval(timer); }
}, 1000); // run every second
Then make saveTimestamp function either redirect browser to another page or make ajax call to sync with server.
On server, make a check if user reached this point after less than 25 minutes, and if he didn't (no cheating), perform standard writing to SQL (I can't help you much with server-side, as I've never worked with Java servlets).
I have been reading the documentation, and cannot seem to find a method to set the date from the server as opposed to the client?
For example something like this
moment().set('server time')
Then moment() would return the Date Object based on server's time as opposed to the time from the client's computer.
Does this functionality exist, and if not what are some recommended methods you would use? Right now I am polling the server to get the server's time, but as you can imagine this is not very efficient.
UPDATED WITH CODE EXAMPLE AND SUMMARY
I am building an auction application. So server time is critical. For example if the user has tampered with their time settings or their time has been manually configured, the client might see an auction that has already ended, when in fact it still has a few minutes left. All time checks are obviously done on the server, but that is why I need the client and server to be in sync. Now you can see I am polling the server to get the latest time every few seconds. However what I need is to set moment() to call the base time from the variable I pass from the server. So everytime I call moment() it bases the time from the time passed in initially instead of new Date().
app.getTime = ->
setInterval ->
$.get app.apiUrl + 'public/time', (time) ->
app.now = moment(time).format('YYYY-MM-DDTHH:mm')
, app.fetchTimeInterval
Somewhere else in my application I use the app's server time like so
collection = new Auction.DealershipBasket [], query: "?$orderby=Ends&$filter=Ends lt datetime'#{app.now}'"
Instead I would like to call the following and it returns the time from server which I only need to configure once with a get request from the url above.
now = moment().format('YYYY-MM-DDTHH:mm')
The best way to do this would be to ask the server once for the current time and then compute the offset between the server time and the client time. A function can then return the server time at any stage by using the current client date and applying the server difference.
Here's an example:
var serverDate;
var serverOffset;
$.get('server/date/url', function(data){
// server returns a json object with a date property.
serverDate = data.date;
serverOffset = moment(serverDate).diff(new Date());
});
function currentServerDate()
{
return moment().add('milliseconds', serverOffset);
}
Since Moment.js 2.10.7 it is possible to change the time source (see the PR that has introduced it).
You can use it to synchronize the time Moment.js sees with your server's time.
function setMomentOffset(serverTime) {
var offset = new Date(serverTime).getTime() - Date.now();
moment.now = function() {
return offset + Date.now();
}
}
title: Changing Time Source
version: 2.11.0
signature: |
moment.now = function () { return +new Date(); }
If you want to change the time that Moment sees, you can specify a method that
returns the number of milliseconds since the Unix epoch (January 1, 1970).
The default is:
moment.now = function () {
return +new Date();
}
This will be used when calling moment(), and the current date used when tokens are omitted from
format(). In general, any method that needs the current time uses this under the hood.
Changing Time Source
Let's try this:
var momentFromServer = moment(input);
var clampedMoment = momentFromServer.max();
I've found this is mentioned in momentjs documentation.
Sometimes, server clocks are not quite in sync with client clocks. This ends up displaying humanized strings such as "in a few seconds" rather than "a few seconds ago". You can prevent that with moment#max():
https://momentjs.com/docs/#/manipulating/max/
This is a really basic JavaScript question and probably duplicate, but I don't know the answer!
I have code as follows:
function userlist_change(myval, function_type) {
// relatively slow code involving Ajax call
// based on Ajax results, change some client-side stuff
}
$("#subjectlist").change(function() {
userlist_change($("#subjectlist").val(), 'change');
}).change();
$("#subjectlist").keypress(function() {
userlist_change($("#subjectlist").val(), 'keypress');
});
I have the problem that if the .change() event is called, the userlist_change function kicks off, and it's relatively slow. If the user changes the list again (e.g. by typing), my code waits for userlist_change to complete before restarting it with the new value.
This looks quite odd in the UI, as it can take a few seconds for anything to change client-side - and sometimes the results of the first call only appear after the user has already made a second call.
Is there any way I can interrupt any existing userlist_change process when the .change() or `keypress() event is fired?
[EDIT] What would be ideal is a simple 'kill any running functions with this name' command - is this possible? Or do I really have to fiddle around with timers?!
you can store last request time in a global variable, and store a request time in each ajax request, so that when you are just showing the result of first request, if the global last request time is greater than request, request time, you should show, other wise not. For example:
var lastRequestTime;
function userlist_change(myval, function_type,requestTime) {
// relatively slow code involving Ajax call
// based on Ajax results, change some client-side stuff
if(lastRequestTime <= requestTime){
//show
}
}
$("#subjectlist").change(function() {
lastRequestTime = new Date();
userlist_change($("#subjectlist").val(), 'change',lastRequestTime );
}).change();
$("#subjectlist").keypress(function() {
lastRequestTime = new Date();
userlist_change($("#subjectlist").val(), 'keypress',lastRequestTime );
});
You should use throttling of event. It is quite easily done with RX for JavaScript, but library is quite complicated. You can try filter value with timer.
Here is useful plugin for throttling: http://benalman.com/projects/jquery-throttle-debounce-plugin/
For some reason this check for new chat messages causes a larger amount of browser (and to some extent server) load than I would expect. Anyone see any ways that I can make it more efficient, to lessen the load?
// Begin the cycle of refreshing the mini chat after the standard delay.
function startRefreshingMinichat(){
var secs = 30; // Chat checking frequency.
setTimeout(function (){
checkForNewChats();
startRefreshingMinichat(); // Loop the check for refresh.
}, secs*1000);
}
// Check for the latest chat and update if it's different.
function checkForNewChats(){
// Check whether the latest chat doesn't match the latest displayed chat.
// NOTE THAT THIS CALLBACK DOES NOT TRIGGER IMMEDIATELY.
$.getJSON('api.php?type=latest_chat_id&jsoncallback=?', function(data){
var newChats = false;
// Update global data stores if an update is needed.
if(updateDataStore(data.latest_chat_id, 'chat_id', 'latestChatId', 'chat_id')){
newChats = true;
}
if(newChats){ // there are new chats to show.
refreshMinichat(null, 50); // loads new chat content.
}
// Since this callback isn't immediate, any feedback has to occur whenever the callback finishes.
}); // End of getJSON function call.
}
Check out CometD. It's a js long-polling system I've used with some success for simple chat systems integrated with jQuery. (Last time I looked, there were a few jQuery specific implemetations, but I never found one that was robust enough for me.)
you can checkout this push engine so that you have not to poll for new data anymore.
check it out, its really cool.
How to call or make the javascript function from the Application_Start of global.asax in asp.net mvc(C#) application?
You can remember the last "invoked" time in Session or cookies (which is easier for javascript but worse for performance/etc) and then
function check() {
// or var lasttime = <%= Session["lasttime"] %>;
if (now - $.cookie("lasttime") > timeout)
{
$.cookie("lasttime", now);
performAction();
}
window.setTimeout(check, 1000);
}
You can call time function once from $(document).ready().
But note that it may take browser several seconds to render page, or it may bump into 404 or other errors and page will be inactive... javascript is not a reliable way to do scheduled actions.
Another way is to have your timer on server. JavaScript function like above will just ask for it from time to time, passing user ID or something like that. This will prevent timer reset during page reload. But you'll have to do request too often. So the best solution would be to combine two techniques:
Run timer on server
When page is renders, set var inited = false;
Run function above but like this: if (!inited) timer = $.getJSON("/timer?uid=x"); and when you have the precise current timer you can continue with JavaScript only, without server requests.
"The javascript function gets the data to be shown to the User from database through jquery. The javascript function will be executed periodically using setTimeout"
This wouldnt be the place to do it.
Have you thought about using your masterpage?
Since JavaScript executes on client side and global.asax executes on server side. You cannot do that.
How about you check a Application level variable at the load of your landing page (master page would also do) and register whatever the javascript there and set the variable.
You can skip the registration if the variable is set.