PHP executing ajax calls sequentially - javascript

This is driving me nuts for a while now. I have an ajax call like so:
function update()
{
$.get("update.php", function(data)
{
$("#output-progress").html(data);
});
}
And I call it like so:
window.setInterval(function()
{
update();
}, 2000);
}
Then I have another calc function which is also called:
function calc()
{
$.get("calc.php", function(data)
{
//whole bunch of lines to re-render page
});
}
So the idea is that while calc() is running, the update() will periodically update a div on the progress.
However what is happening is that if I open the console and check the calls to update() is triggered every 5 seconds, but they just stall and they complete only after the calc() has returned. I first thought this was a browser/jQuery issue, but if I log both the functions into separate log files in PHP then the update() gets logged only after the calc() finishes!
Im not sure what is going on here, any pointers are greatly appreciated!

Most likely, you are using sessions, and both calc.php and update.php access session data. In order to ensure data consistency in sessions, access to session data is locked, so only one php process can access the session at a time. This means that while calc.php has the session, no other page access can read it.
What you will want to do is call session_write_close() after calc.php has finished anything that might require access to the session, and before it starts its time-consuming task.
session_write_close() writes the current session's data and releases the lock. Once calc.php is no longer holding to the session, accesses from update.php can read it.

Related

Meteor run a function after database connection

I need to read from the database and aggregate some results, and then set a number of reactive variables on the client. I can only do this after the database has been connected.
I tried to do it in onRendered,
Template.header.onRendered(function(){
recalculate();
});
It works locally, but not when deployed to meteor.com. Where should I do the function call?
The onRendered callback has nothing to do whatsoever with data over the wire, it simply tells you when the template appears on the DOM (unless you archaically wait for the data to start rendering).
It works locally because the data is very fast to arrive and can be ready before a template rendering (which takes a few milliseconds).
However on real conditions latency appears: the data takes a while to arrive.
Since you use an inappropriate way to know how your data is ready, stuff goes wrong. It would have failed just as badly if you had used any other kind of arbitrary trigger:
setTimeout(recalculate, 150);
To know when the database has connected, use the subscription's built-in ready callbacks:
var dataSub = Meteor.subscribe('my data', recalculate); //Method 1
Tracker.autorun(function(computation) {
if(dataSub.ready()) {
computation.stop();
recalculate();
}
}); //Method 2
Choose one of the two methods.
The second one is more modular since you can have multiple computations watching one subscription.

Javascript window.location calls getting lost?

I am having some trouble with a bit of code. I have a function that does some stuff to some data, calls a remote system (activating a script on that system and passing in the data), and then makes another call to the same system to activate a different script (which acts on the data saved above). The problem is that the 1st call to the remote system appears to get lost in the execution.
This is being run in Safari, uses jquery; the function is tied to a button click, which is defined in the javascript code with an onclick function (i.e. it is not defined in the html button definition).
Here's a rough breakdown of the function (cleaned out for viewing purposes - I hope I left enough to make it clear):
function compareJSON() {
// loop through the objects, testing and changing data
// ...
dataSession=({ //build object for output });
$.each( dataSession.chapters , function( indexC, value ) {
//compare objects to some others, testing and changing data
});
// ...
//Call remote script on other system
urlString="url://blah.dee.com/Blar?script=SaveJSON&$JSONobject=";
window.location= urlString + JSON.stringify(dataSession);
//Call remote script on other system
window.location="url://blah.dee.com/Blar?script=EditJSON";
}
The last three lines of code are the two calls. It uses the window.location to actually trigger the remote system, passing the data through the URL. But I need BOTH scripts to get called and run. It appears that only the LAST script in the sequence ever gets run. If I switch them around it remains whatever is in last place.
Is there something about the window.location that doesn't actually process until the end of the function?
This script actually used to be a series of separate function calls, but I figured I was running into asynchronous execution that was causing the various script calls to not register. But once I put the code into this single function, it was still happening.
Any clues would be helpful.
Thanks,
J
Modifing the value of window.location is reserved exclusively for instances in which you'd like to cause a browser redirect.
It looks like you want to trigger a page request instead. You say you already have jQuery loaded, if so, you can trigger such a request using jQuery.get or a similar function.
For example:
// Loads the myscript.php page in the background
$.get('myscript.php');
// You can also pass data (in the form of an object as the second argument)
$.get('myscript.php', { name: "John", time: "2pm" });

Prevent JavaScript Timer Re-entry

My ASP.NET MVC page uses JavaScript/jQuery to poll my database every second.
This is working but I want to make sure that, if there is a delay, my timer handler won't get called again before it has returned.
In there any trick to this other than storing the timer ID in a global variable, clearing the timer in my handler, and restarting it when my handler is done.
NOTE: I realize every second seems frequent but this code is polling my server after submitting a credit card payment. Normally, it will only run for a second or so, and I don't want the user to wait any longer than necessary.
Polling every second? That's quite heavy!
That aside, you won't have this issue when setTimeout is used instead of setInterval. The latter ensures that a piece of code is run x times given a interval, while the former ensures that there's a delay of at least x milliseconds.
function some_poller() {
$.ajax({
url: '/some_page',
success: function() {
setTimeout(some_poller, 1000);
},
error: function() { // Also retry when the request fails
setTimeout(some_poller, 1000);
}
});
}
// Init somewhere
some_poller();
Not really, although I wouldn't recommend using a global variable. Stick it inside some function.
But are you really sure you need to poll every second? That's an extremely chatty interface.
In my personal experience a "global", (inside of the root function), variable works very well in this instance so that you can control when to clear and restart. If the response is really as quick as you say, this shouldn't cause too much overhead, (clearing/resetting), and will allow to account for these type of situations.

How to detect when several AJAX requests have completed or failed?

I have an app that loads several resources when it's first run, which are stored in localStorage. I have a function that checks whether all the local storage variables are set, so that part is working okay.
My method of working is like this:
Display a loading message.
Initialize the AJAX requests.
Start a timer interval to check if everything has loaded.
When the data has loaded, initialize the application etc.
If the data did not load, display an error message.
The problem is with #5 - how to detect if there was an error? For example if there was a connection problem or the sever sent back invalid data for whatever reason. Here is my current code - downloadData just performs a basic AJAX request:
// check local storage and download if any missing
if ( !checkLocalStorage() )
{
$('#content').before( '<div class="notice" id="downloading">Downloading data, please wait...</div>' );
for ( var i in db_tables )
{
if ( localStorage[db_tables[i]] == null )
downloadData( db_tables[i] );
}
}
// check progress
var timer = setInterval( function() {
if ( checkLocalStorage() )
{
// everything is downloaded
$('#downloading').hide();
clearInterval(timer);
initApp();
}
}, 500 );
Could you turn it around a bit? Something like this (with sensible variable names and a "real" API) would simplify things:
Display a loading message.
Instantiate an application initializer, ai.
Crank up the AJAX requests:
Success handlers call ai.finished(task).
Error handlers call ai.error(task).
Register with the initializer, ai.register(task), in case a "you're taking too long" check is desired.
Once all the AJAX requests have called ai.finished, initialize the application etc.
If any of the AJAX tasks called ai.error, then display an error message and start cleaning things up.
This way you wouldn't need to setInterval() and the individual AJAX tasks will tell you when they have finished or fallen over. You might still want the interval to deal with tasks that are taking too long but most of the logic would be notification based rather than polling based.
Seeing your actual ajax calls in downloadData would help, but I suggest you look over the jquery AJAX API again. Ajax calls have callbacks not just for overall completion but specifically for success and failure including errors. Try to do something like retrying if there is an error and if it continues to fail you can warn the user. You can also use these callbacks to notify your application when the loading is done instead of using an interval timer.

Call javascript function from global.asax in asp.net mvc

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.

Categories