I'm trying to develop an application in which it is very important to detect changes in a database in real time. I have devised a method to detect the changes now by running an ajax function and refreshing the page every 3 seconds, but this is not very efficient at all, and on high stress levels it dosen't seem like an effective solution.
Is there any way I can detect if some change has been made in the database instantly without having to refresh the page? The sample code is attached. I'm using php as my server side language, with html/css as the front end.
$(document).ready(function() {
$('#div-unassigned-request-list').load("atc_unassigned_request_list.php");
$('#div-driver-list').load("atc_driver_list.php");
$('#div-assigned-request-list').load("atc_assigned_request_list.php");
$('#div-live-trip-list').load("atc_live_trip_list.php");
setInterval(function() {
$.ajax({url:"../methods/method_get_current_time.php",success:function(result){
$("#time").html(result);
}});
}, 1000)
setInterval( function() {
$.ajax({url:"atc_unassigned_request_list.php",success:function(result){
$("#div-unassigned-request-list").html(result);
}});
$.ajax({url:"atc_driver_list.php",success:function(result){
$("#div-driver-list").html(result);
}});
$.ajax({url:"atc_assigned_request_list.php",success:function(result){
$("#div-assigned-request-list").html(result);
}});
} ,2000);
});
Please help!
For me, the best solution is
On the server side write a service that identify the changes
On the client, check this service with websockets preferencially (or ajax if you can not use websockets), then if there have changes, download it, This way you have, economy and velocity with more funcionality
Examples Updated
Using ajax
function downloadUpdates(){
setTimeout(function(){
$.ajax({
url: 'have-changes.php'
success:function(response){
if(response == 'yes'){
// ok, let`s download the changes
...
// after download updates let`s start new updates check (after success ajax method of the update code)
downloadUpdates();
}else{
downloadUpdates();
}
}
});
}, 3000);
}
downloadUpdates();
Using websockets
var exampleSocket = new WebSocket("ws://www.example.com/changesServer");
exampleSocket.onmessage = function(event) {
if(event.data != "no"){
// ok here are the changes
$("body").html(event.data);
}
}
exampleSocket.onopen = function (event) {
// testing it
setInterval(function(){
exampleSocket.send("have changes?");
}, 3000)
}
Here (I have tested it ) and Here some examples of how to use websocokets on php, the problem is you will need to have shell access
Related
I'm creating online chat, but I'm wondering while using jQuery .load() in my script, my browser seems to get slow. When i checked the inspect element "Net" section, it loads bunches of GET-data... etc.
I would like to know if there's a better script solution with this code to prevent chat being heavy in the background while the data keeps looping in the background to check who's keep coming online/offline.
setInterval('loadThis()', 5000);
function loadThis () {
$("#loads").load('includes/users.php', function(){
$(".chat-side-panel li").each(function(i){
i = i+1;
$(this).addClass("stats"+i);
var status = $(".stats"+i).find("span.bullet").data("status"),
flag = $(".stats"+i).find("span.mail").data("flag");
if(status == 1) {
$(".stats"+i).find("span.bullet").addClass("online");
}
if(flag == 1) {
$(".stats"+i).find("span.mail").addClass("active");
}
});
});
}
the Chat-Side-Panel will be the main panel, and LI will be the listings of users including their status (online/offline) and flag (message received). As for the standard, what can you suggest for the setInterval time loading (if 5sec. is enough) or should i increase it.
Thanks for your input for this.
PS. We're doing this with both PHP/MySQL also.
One issue I see is that you keep re-querying the DOM for the same elements. Get them once, re-use them thereafter:
var load_target = $('#loads');
function loadThis () {
load_target.load('includes/users.php', function () {
load_target.find('.chat-side-panel li').each(function (i) {
var stats_li = $(this),
bullet = stats_li.find('span.bullet'),
mail = stats_li.find('span.mail');
bullet.toggleClass('online', (bullet.data('status') == 1))
mail.toggleClass('active', (mail.data('flag') == 1));
});
});
}
I don't know all of your involved logic or what the rest of your system looks like, so this particular code may not work exactly. It should simply serve as a re-factor done in a vacuum to show what that function could look like if you stopped hitting the DOM so hard.
Also, use of setInterval is not generally recommended. If the load of the remote file takes a while, you could end up calling loadThis() again before a previous one was completed. This would compound your DOM issues if calls to loadThis() began stacking up. Recursive use of setTimeout is preferred in a situation like this. Here is the above code modified to run recursively, and some usage examples below that:
var load_target = $('#loads'),
loadThis = function (start_cycle) {
$.ajax({
url: 'includes/users.php',
dataType: 'html',
type: 'GET',
success: function (response) {
load_target
.html(response)
.find('.chat-side-panel li').each(function (i) {
var stats_li = $(this),
bullet = stats_li.find('span.bullet'),
mail = stats_li.find('span.mail');
bullet.toggleClass('online', (bullet.data('status') == 1))
mail.toggleClass('active', (mail.data('flag') == 1));
});
},
complete: function () {
if (typeof start_cycle !== 'boolean' || start_cycle) {
load_target.data('cycle_timer', setTimeout(loadThis, 5000));
}
}
});
};
//to run once without cycling, call:
loadThis(false);
//to run and start cycling every 5 seconds
loadThis(true);
// OR, since start_cycle is assumed true
loadThis();
//to stop cycling, you would clear the stored timer
clearTimeout(load_target.data('cycle_timer'));
Last years (around 2012) I developed a chat system for a social network, and saw that
Using setInterval issue is when the request is being sent regularly, without waiting or carry about the result of the first requests in the queue. Sometimes the script can not respond and Mozilla or IE asks the user whether he should block or wait for the non-responding script.
I finally decided to use setTimeout instead. Here is what I did (I use $.getJSON so please study the example and how can use load instead)
function loadThis () {
$.getJSON('url').done(function(results){
//--use the results here
//then send another request
setTimeOut(function(){
loadThis();
},5000);
}).fail(function(err){
//console.log(print(err))
setTimeOut(function(){
loadThis();
},1000);
});
}
loadThis();
PS.: I would like to mention that the time depends on our many items are to be retrieved in your users.php file. Maybe you should use the paging tip. Your users.php can then treat url params users.php?page=1&count=100 for the first request, users.php?page=2&count=100 for the second until the results rows number is 0.
EDITS: In addition, I suggest you consider not interacting with the DOM every time. It is important too.
i need a a script that will refresh the functions:
$ping, $ms
every 30 seconds, with a timer shown,
i basicly got this script:
window.onload=function(){
var timer = {
interval: null,
seconds: 30,
start: function () {
var self = this,
el = document.getElementById('time-to-update');
el.innerText = this.seconds;
this.interval = setInterval(function () {
self.seconds--;
if (self.seconds == 0)
window.location.reload();
el.innerText = self.seconds;
}, 1000);
},
stop: function () {
window.clearInterval(this.interval)
}
}
timer.start();
}
but it refreshes the whole page, not the functions i want it to refresh, so, any help will be appriciated, thanks!
EDIT:
I forgot to mention that the script has to loop infinatly
This here reloads the whole page:
window.location.reload();
Now what you seem to want to do is reload portions of the page, those portions having been generated by php functions. Unfortunately php is server side so that means you cant get the client browser to run php. Your server runs the php to generate stuff that browsers can understand. In a web browser open a page you made using php and choose to view source and you'll see what I mean.
Here's what you'll need to do:
Make your two functions ping and ms accessable via ajax
Instead of window.location.reload() do a call to jQuery.ajax. on success write to your page
Here's what I think would be the ideal way of dealing with this... I haven't seen the php side of your problem but anyway:
make a file called ping.php and put all your ping function code in there. ditto for ms
in your original php file that called those functions, make a div at each point where you wanted a function call. Give them appropriate ids. Eg: "ping_contents" and "ms_contents"
You can populate these with some initial data if you want.
In your js put in something like this:
jQuery.ajax(
{
url : url_of_ping_function,
data : {anything you need},
type : 'POST', //or 'GET'
dataType: 'html',
success : function(data)
{
document.getElementById("ping_contents").innerHTML = data;
}
});
do another one for the other function
What you want is AJAX, Asynchronous JavaScript and XML
You can use jQuery for that.
I can put an example here, but there is a lot of information to be found on the internet. In the past I wrote my own AJAX code, but since I started using jQuery, it's all a lot easier. Look at the jQuery link I provided. There is some usefull information. This example code might be the easiest to explain.
$.ajax({
url: "test.php"
}).done(function() {
alert("done");
});
A some moment, for example on a click on a button, the file test.php is executed. When it's done, a alert box with the text "done" is shown. That's the basic.
The function below grabs a php page, then reloads it every 5 seconds. The only thing coming from that roomdata.php page is a string with a color name (blue, yellow, etc.). I wanted to be able to use that name in the function modifyLight(color), but it's not letting me. I don't know why, but no matter what I tried, it's not treating the variable data as a string, even if I clarify it as one.
Any help is appreciated, thanks!
$(function(){
function loadData()
{
var data = load('roomdata.php');
modifyLight(data);
setTimeout(loadData, 5000); // makes it reload every 5 sec
}
loadData(); // start the process...
});
You are using async ajad calls. You need to configure your request to be sync.
$.ajax(URL, {async : false});
In that way the execution of the next line will be done until the ajax request Is finished.
EDIT
Your function should be like this:
$(function(){
function loadData() {
$.post("roomdata.php", function(result) {
modifyLight(result);
setTiemout(function() { loadData(); }, 5000);
}
}
loadData(); // start the process...
});
The problem with the way you were doing it is that $.load(); only loads something with Ajax and put the content on $('#yourdiv'); It does not return anything. You need an ajax request with something in the "success" event. In the code I gave you, $.post makes an ajax request via post to roomdata.php and then, once the ajax is finnished, it executes the function function(result) { ... }
To consolidate a few SQL calls I'm trying to make one query to the server and then have the client side iterate through each result. The caveat is that I need to wait for user input before processing the next result. Is this possible?
I have a jquery call similar to below:
$.post('functions/file_functions.php', {type: 'test', f: 'load'}, function(data) {
if (data.success) {
$.each(data.files, function() {
// Can I wait for user input at this point and then process the next
// file after a users interaction (e.g. a button click)?
});
}
}, "json");
I'm going to expand on my comment a bit, and hopefully make it a useful answer. JavaScript is single-threaded, so there's no way to block the execution of a function while waiting for something else (such as an element being clicked on) to happen. Instead, what you could do is store the list of files into an array when the AJAX POST request returns successfully, then use a separate click event handler to cycle through them (I assume getting one file per click).
Code may look something like this:
$(function() {
var files, index = 0;
$.post('functions/file_functions.php', {type: 'test', f: 'load'}, function(data) {
if (data.success) {
files = data.files;
}
}, "json");
$('.mybutton').click(function() {
if(files) {
var file = files[index++];
// do something with the current file
}
});
});
One of the ways to have "blocking" user input in javascript is to call window.prompt (among others like window.confirm, or window.showModalDialog). However its not really customizable, you might want to just save the data coming back from the server and have some kind of a user input event based processing.
In code it would look like this:
var the_answer = window.prompt("What's the airspeed velocity of an unladen swallow?");
console.log(the_answer);
I'm doing a long poll method chatroom. But it seems that, when a long poll occurs and I refresh the page in chrome OR i try to send another async request everything times out (i.e i cant load my domain again until i close/reopen the browser).
My client side code is:
$(document).ready(function() {
setTimeout(
function () {
longPollForMessages();
},
500
);
});
function longPollForMessages()
{
$.ajax({
url: url,
dataType: 'json',
success: function(data) {
$('#chat_messages').append('<div>'+data.messages+'</div>');
longPollForMessages();
}
});
}
And my serverside:
while(true) {
$messages = $db->getMessages();
if (!$messages || sizeof($messages)==0) {
sleep(1);
} else {
echo '{"message":'.json_encode($messages).'}';
die();
}
}
Any ideas? Assume no syntax errors.
I can see you have already answered your own question, but I recently had a similar problem and found another way to handle it is to disable the setTimeout on ajax call, then restart it on success. That way you aren't pinging your server for information when it isn't ready to give it.
I figured it out from this question: stackoverflow.com/questions/4457178/… - php locks a given session until the page is done loading so the second ajax call wasn't able to go through. You have to release the lock by calling session_write_close();