Putting live score from database using AJAX and jQuery - javascript

So I'm having a database which gets updated after getting score of a match.
Right Now I'm able to make ajax get request to my route for getting the latest score from database on $(document).ready(function() and change my html to show score but it is static and does not gets updated.
So my question is how to make this ajax request in a loop. Right now a user has to refresh to make the request again and get the updated latest score.
I am using mongoose, mongodb, nodejs on express framework, and jquery for scripts.
This is my nodejs route for handling ajax request, it returns json of match data
router.get('/matchData',function(req,res){
Match.getMatchData(function(err,match){
if(err) throw err;
res.send(match);
});
});
This is my script for AJAX.
$(document).ready(function(){
$.ajax({
type: 'GET',
url: 'http://localhost:3000/matchData',
dataType: 'json'
})
.done(function(data) {
$('.team1').text(data.title);
$('.team1odds').text(data.values.t1odds);
$('.team1probability').text(data.values.t1probability);
$('.team1score').text(data.values.t1predict);
$('.team2').text(data.title);
$('.team2odds').text(data.values.t2odds);
$('.team2probability').text(data.values.t2probability);
$('.team2score').text(data.values.t2predict);
})
.fail(function() {
alert("Ajax failed to fetch data")
});
});

There are multiple ways to do this, the easiest would be to use long polling, but it is also the most ineffective.
Very simple example:
var seconds = 5;
setInterval(function runner() {
// run your ajax call here
var result = callAjax();
}, seconds * 1000);
A much better way would be to use websockets, as the score gets updated server-side you push the event to the client.

Related

Why is my async jQuery ajax call blocking?

I have read many similar questions to mine from long ago but have yet to find the answer to my problem, so apologies if it sounds so familiar.
I have a Laravel/PHP web app which loads in an excel file of transactions. These are processed as either success or failure. In development it takes about two seconds per transaction. A typical file has about 40 transactions. I am now wanting to use the Bootstrap progress bar to provide feedback to the user about how far along the processing is going.
I have a page with a button to fire the import, previously file selection and things have happened, so I can just call the backend URL (audit.import) with the correct parameters and the upload will happen and work. So what I have done, is create a URL to return the status of the upload from the server (loadprogress). The plan being that the loadprogress will be called via ajax and the magic of js setTimeout, in order to poll the backend. Once we see all records have been successful or not, then the poll can end.
The problem is, the loadprogress poll fires regularly, right up until I press the button to start the main file load. Then it fails to fire again until the main file load has completed, thus removing the planned use for the progress meter.
My javascript looks like this,
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
var fullname = '<?php echo $fullname; ?>';
$("#ajaxButton").click(function(event) {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
url: '/audit.import/1/' + fullname,
type: 'POST',
async: true,
}).always(function(xhr, status) {
console.log("Import complete with status of " + status);
});
console.log("sent async call to perform audit");
});
(function loadProgress() {
$.ajax({
type: 'GET',
url: '/loadprogress',
}).done(function(result) {
console.log(result);
}).then(function() {
setTimeout(loadProgress, 100);
})
})();
});
</script>
I am on a mac in safari, but have tried chrome on mac with the same results.
Any assistance would be welcomed.
Thanks.
It was indeed a server side problem. I was running on a single threaded test server which means there was no second thread for my second process. Hence the block. By default the test Laravel server that comes with the install is only single threaded. A fact I had missed in my setup of the test server.

Aborting / canceling running AJAX calls before execute new AJAX in JS

I've never done this type of manipulation of AJAX calls (to stop/abort/cancel or ignore? already running AJAX calls before the execution of a new one) before so I really don't understand how to do that and would appreciate some direction.
I have a page in my app where I make a number of AJAX calls to fill dynamically the data in my table (Object Name, Object Fit, Object Progress) when the page loads. For example, there are 5 rows in the table. So I call
$.post("/getFit", {objectId: objectId}, function (result) { manipulation with result }
and
$.post("/getProgress", {objectId: objectId}, function (result) { manipulation with result }
5 times each in the loop -- one for each of the objects.
The first column of my table has links to more detail on the object, and clicking on them I call another AJAX:
$(document).off('click', '.js_object').on('click', '.js_object', function (e) {
var objectId = $(this).attr("id")
$.post("/viewObject", {objectId: objectId}, function (result) {document.getElementById("main_window_content").innerHTML = result; });
})
The problem is that the browser will not render the results of the last AJAX call (/viewObject) until it has received the results of all of the previous calls (/getFit x5 and /getProgress x5).
As a result, a user that wants to drill into the detail on an object needs to wait until the AJAX calls for the other objects are complete before they see anything.
So I struggle with how to stop/abort/cancel (or ignore?) "/getProgress" and "/getFit" so we can fully execute "/viewObject" and view the results of it.
I would very much appreciate your help.
Use xhr.abort() to kill the xhr requests as shown in the below code in JS. I believe there is ajax.abort(); in JQuery
var xhr = $.ajax({
type: "POST",
url: "XXX.php",
data: "name=marry&location=London",
success: function(msg){
alert( "The Data Saved: " + msg );
}
});
//kill the request
xhr.abort()
If you want execute one ajax after another, and you need all requests to work to show the final result, you can use .done():
$.ajax({
url:'/getFit',
data:{objectId:objectId}
})
.done(function(data){
//do something with the results then call /getProgress
$.ajax({
url:'/getProgress',
data:{objectId:objectId}
})
.done(function(data){
//do something with the results then call /viewObject
$.post("/viewObject"....
})
});
That way you only show /viewObject if the others calls were successfull

Javascript ajax request callback without waiting for response

I know we can make a javascript ajax request from some server and it either receives the response or gives timeout error after some time.
Let's consider this scenario when we don't want to wait for the request rather the server would send a response(or we can say it would be another request from server to client) async at any time after getting the request and then call a javascript CB function with the response.
I am looking for ideas for how to go about it mainly supporting all modern browsers and if possible not relying on any 3rd party plugin except may be jQuery.
The main feature of Ajax is that it IS asynchronous by default, and your program will continue to run without waiting for the response. So unless I'm misreading your question, it is what you need.
If you use jquery, then you pass in a callback function that will execute only when the server sends back a response. You can specify a timeout in the settings, though I'm not sure what the maximum time you can provide without getting a timeout error. But it will be several seconds, at least.
You can even specify different callbacks for success and fail as follows (adapted from the jquery ajax API, but added a timeout of 5 seconds):
var request = $.ajax({
url: "http://www.some.url/",
method: "GET",
data: { some : stuff },
dataType: "html",
timeout: 5000
});
request.done(function( data ) {
console.log( "SUCCESS: " + data );
});
request.fail(function() {
console.log( "Request failed");
});
I came across this question after 4 years. I dont remember in what context I asked this but for anyone who has the same query:
Http is a request/response protocol. Which means the client sends a request and the server responds to that request with some message/data. Thats the end of the story for that request.
In order for the server to trigger something on the clientside we will have to use something that keeps the connection to the server rather than ending the communication after getting the response. Socket.io is bi directional event driven library that solves this problem.
To update a cart (PHP Session storage and reserve the stock of items in database) on my online shop, I simply add a timeout of 100ms after calling it and remove Success/Error callback.
$.ajax({
url: 'http://www.some.url/',
method: 'GET',
data: {
some : 'stuff'
},
dataType: 'html',
timeout: 100
});
Note : It doesn't matter if some requests didn't arrive, because when the order is saved, an update of the whole cart is sent with a callback.
If your query needs acknowledge, don't use that solution !
I believe your question is similar to this
by Paul Tomblin. I use the answer provided by gdoron, which is also marked as the best solution, and also the comment by AS7K.
$.ajax({
url: "theURL",
data: theData
});
NB: No async parameter provided.

How can I check for live updates without using setInterval/timeout?

Building a social network, I'm trying to fetch live notifications. Currently, the site sends an AJAX request every few seconds using setInterval. It looks something like this:
setInterval ( function(){
url = base_dir+"/ajax/file.php";
data = "data=someData";
$.ajax({
type: "POST",
url: url,
data: data,
dataType: "json",
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType("application/json;charset=UTF-8");
}
},
success: function(JSON){
// retrieve data here
}
});
}, 5000);
That works perfectly, but I'm very worried about that creating servers overload. I tried the comet technique but for some reason it sends much more requests than the above code.
Is there any other more useful technique for pushing this data live?
EDIT:
For implementing long polling I used the following (used the example mentioned here: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery):
(function poll(){
url = base_dir+"/ajax/file.php";
data = "data=someData";
$.ajax({
type: "POST",
url: url,
data: data,
dataType: "json",
beforeSend: function(x) {
if(x && x.overrideMimeType) {
x.overrideMimeType("application/json;charset=UTF-8");
}
},
success: function(JSON){
// retrieve data here
},
complete: poll,
timeout: 5000
});
})();
There's a possibility that I might not get the comet principle right.
PHP code:
// Checks for new notifications, and updates the title and notifications bar if there are any
private static function NotificationsCounter (){
//self::$it_user_id = query that retrieves my id for further checks;
//$friend_requests_count = query that retrieves the friend requests count;
//$updates_count = query that retrieves the updates count;
$total_notifications = $friend_requests_count+$updates_count;
if ($total_notifications > 0) $addToTitle = "(".$total_notifications.")";
else $addToTitle = "";
if ($updates_count > 0) $counterHTML = "<span class='notification_counter' id='updates_counter' style='float: right;'>".$updates_count."</span>";
else $counterHTML = "";
$data = array("counter"=>$total_notifications,"addToTitle"=>$addToTitle,"counterHTML"=>$counterHTML,);
echo json_encode($data); // parse to json and print
}
Since Facebook uses PHP as well, how do they do it?
You should use websockets. You can connect to the server and register onmessage handler. Whenever the server has anything to be send to client, your handler will get invoked. No timeout needed.
Check for websocket support in your browser. As of now, only Chrome, Opera and Safari support them.
if ('WebSocket' in window){
/* WebSocket is supported. You can proceed with your code*/
} else {
/*WebSockets are not supported. Try a fallback method like long-polling etc*/
}
Connecting
var connection = new WebSocket('ws://example.org:12345/myapp');
Handlers
connection.onopen = function(){
console.log('Connection open!');
}
connection.onclose = function(){
console.log('Connection closed');
}
connection.onmessage = function(e){
var server_message = e.data;
console.log(server_message);
}
Documentation: http://www.developerfusion.com/article/143158/an-introduction-to-websockets/
Websockets will be the way to go once they are more universally implemented across the major browsers - I would guess a minimum of 5 years.
The last I heard Facebook chat uses comet and a whole bunch of servers. If you want something more lightweight I can think of two options.
Reduce the polling interval. This is strictly a UI issue - users may have a perfectly acceptable experience with intervals as long as a couple minutes. The only way to know for certain is through user testing, but polling every 5 seconds is probably overkill. No matter what you choose as the optimal interval, this does give you an quick way to scale if you are getting hammered - just crank up the interval until the servers stop melting.
Use HTTP validation caching. You can make the requests more lightweight if the server only returns a response body when the content has changed since the last request. You will have to build something custom using ETag or Last-Modified headers and a lightweight modification checking system on the server, but it might save you a few bytes.

Simple long polling example with JavaScript and jQuery

I'm trying to create a real-time website analytics dashboard which creates an open HTTP connection to the server using jQuery/JavaScript asynchronously to poll the server for updates to the data as and when they occur.
The obvious start for this would be to use an XMLHttpRequest object or jQuery's $.ajax method to send a GET or POST request to the server asynchronously requesting some data.
However, beyond sending one request at a time using a setInterval method every 30 seconds I am not sure how to make the connection to the server persistent. Basically, I only want to send one http request and ensure the connection to the server stays open for polling!
My example code with setInterval is as follows:
<div id="analytics"></div>
<script>
var analytics = document.getElementById('analytics');
setInterval(function(){
$.ajax({ url: "http://server.com/", success: function(data){
analytics.innerHTML = data;
}, dataType: "json"});
}, 30000);
</script>
After searching online, this was the answer I was looking for which doesn't use sockets.io nor WebSockets but does use jQuery by taking advantage of its complete method to create an artificial loop:
<div id="analytics"></div>
<script>
var analytics = document.getElementById('analytics');
(function poll(){
$.ajax({ url: "server", success: function(data){
analytics.innerHTML = data;
}, dataType: "json", complete: poll, timeout: 30000 });
})();
</script>
Source is Tian Davis from Technoctave: http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery

Categories