Is it safe to call a script onunload() using AJAX - javascript

I have a webpage where I am displaying 5 puzzles to the user.When the user clicks for next 5 puzzles,I am sending the score of the current page onunload() using AJAX to the scipt updateScore.php to make updations in their account.
I wanted to ask whether it is safe to make such calls onunload()? I read somewhere that in some cases the calls may not be sent because you have very less time on unload,hence the request may be missed.Is it true?
Or can you suggest a better method or time to make updations

Related

Dojo: all xhr / ajax calls seem to be synchronous and block other calls

I am working on a CRM we inherited. Long story short - there is a button that calls a php script which should run in background and we don't need to wait for response.
request(idata+'transferInTimeExec.php',{
sync: false,
preventCache:true,
method:'GET'
});
Now, the transferInTimeExec.php takes an hour to run, it's a very complex script that deals with weekly timesheets for a recruitment company, processes them, does a lot of DB operations etc.
Using Chrome. Every time I press the button to run it, it blocks all the xhr calls until it finishes. CRM is "ajax heavy" and while the script is running, the user can't do anything, if they navigate to another subpage, no xhr requests will resolve until that process we started has finished. Even when I open a new browser tab and try to do something, it won't do it. If I open the CRM in another browser (Firefox) while the script is running, I can use the CRM.
In Network tab - the first one is pending, and as you can see all the subsequential calls to a different Ajax call wait (all have sync:false)
I even replaced the whole logic with PHP function sleep(30) to make it just do nothing for 30 seconds before returning anything - same issue.
I tried XHR in plain javascript, inside onClick on the button HTML markup, rather than Dojo methods - same issue.
I've done a brutal Search/Replace on the whole project, replacing sync:true to sync:false - nothing changed.
I have run out of ideas, maybe anyone here can help to figure this out? Is there a global switch for sync/async? What else could it be if not ajax issue?
Your script transferInTimeExec.php is probably using session. When thats the case, other AJAX Call would not initiate and instead wait for this AJAX Call to Finish so as to not overwrite the session data. Setting AJAX call to asynchronous does not change the behavior.
If this script takes 1 hour to run it is a bad idea to call it as an AJAX from UI. You should setup a Cron, hourly or daily, and perform all the operations in the backend. Of course, you will need to make some adjustment to the script if it is using session.
EDIT
You could use session_write_close(); at the top of your script. This tells the PHP that this script would not write anything to the Session so other AJAX Calls are free to use the Session. However be careful to not write anything to Session after this as this will result in an error.

PHP Mysql: Avoid overflow on pageviews?

So I have certain profile pages that needs to have page views. I stored the view data in mysql and php (actually laravel). Basic idea is to add view by 1 every time the profile is visited.
Basic idea is to add a php code in the profile page, like
$page->view += 1; $page->save();
But what if the user hits f5 several times? It will cause the query to run a lot and I fear it will eventually slow the app.
I was thinking of making a prompt with js when user hits f5 and an ajax call to add the view. But I was wondering if there is a better solution (like, how did youtube do their views)?
You can count the views after a certain amount of time on the page.
To achieve this, you will need a delayed javascript function like:
setTimeout(function(){countView()},3000); (3 second delay)
Where countView() should be an ajax call to a function that runs $page->view += 1; $page->save();
And since Ajax calls are asynchronous, the execution will not delay your application flow, although a simple increment on a page-view table should not do much harm in terms of performance
This will work as long as the user doesnt delete the cookies.
if ($_COOKIE['returning']!="yes")
{
// first visit!
}
setcookie("returning", "yes", time()+360000);
Another way would be to log the IP in a database and check if user already visited, but the code is more complex than i can post right now. I will edit the post later if accepted.

Wait until a callback address is called

I am programming an educational web in PHP and JS and I interact with another webpage that corrects for me some programming exercises.
I don't know when this correction will finish, but this correction webpage calls a given address when the correction is available.
Is it possible to wait for that result with PHP or JS and then do some stuff (not just showing the result to the user), even if the user closes the tab?
Thanks in advance.
STEP BY STEP explanation:
A student is trying to do a programming exercise. The statement of the exercise is shown, as well as other details to complete it.
When he thinks he has reached a solution, he uploads his code. Then, he can wait (or not) for the correction to finish.
My web page uploads then the code file (with other files as well as an address to callback when it finishes) to the corrector webpage.
I keep waiting until the callback is made.
When the correction is finished, I do some stuff like assigning a grade to the student and, if he/she stayed on the same page, he/she can see details of the correction.
The correction is done by another webpage and I don't know when it would finish, but when it finishes it calls a given adress (for example: www.example.com/ex1sub1usr1 ).
The doubts are between step 2 and 3. It is possible to do all this process with PHP/JS? If not, what are the alternatives?
Updated Answer
Create a PHP script on your server which updates your grade database when visited with a specially formulated URL, eg. http://yourserver.com/update.php?user=2429&sub=1&ex=1
specify this as the target URL when you submit for correction
if you are restricted to your /ex1sub1usr1 format then just use regex to parse the URL
When user refreshes (or returns to your site) the data should be appropriately pulled from your PHP backend
For bonus points, you could have your submission screen (or the entire website) intermittently poll another PHP script URL on your server (with XHR) for an "updated" flag, and live update the page.
Considerations
Your only major concern will then be ensuring that the form data (ie. their code) is submitted completely. Consider using XHR to submit your form data and temporarily enabling a window closure warning until upload is complete.
Original "Answer"
Since there isn't much information to go by here, I will have to make a few assumptions:
you presumably can't reliably spawn a process to watch the associated results address
you don't need to notify the user immediately (push notifications), but they need eventually see their result, eg. when they return to your page
results stay around for a while
as you mention, this must work even if the user closes the tab
Given this scenario, I would merely check the results page when the user returns to your site.
Just store the results address in session vars - either via PHP or a cookie - then when the user returns you can perform any unfinished checks and update accordingly.
NB: Should further information surface in the question I will gladly provide further details
You can perform all necessary actions on a script behind the given address that is called by the remote website after the excersises have been corrected.
It is absolutely not possible to show/do anything on client side if the user has closed the tab.

OpenGraph watch action - less than 50% watched

I'm using the Javascript SDK to contact the API.
Using Built-in Watch action:
When a user watches less than 50% of a video, or if a user removes a watch activity from your app/site, you should also remove the corresponding action instance that was published to Open Graph by invoking the following call
DELETE https://graph.facebook.com/[watch action instance id]
My problem is with when the user navigates away from the page.
I've tried to use the jquery unload method to make the delete call to the API but it fails to. I've also tried using ajax to make the call synchronously but this holds/freezes the browser for at least 5 seconds on average.
Any ideas?
I've tried to use the jquery unload method to make the delete call to the API but it fails to.
Well, that’s a problem with the call being asynchronous. Your unload handler fires, starts the request, and then the browser navigates away from the page. Wait, what, there’s a request still running? Let’s terminate that, since I’m about to load and display another page anyway …
I've also tried using ajax to make the call synchronously but this holds/freezes the browser for at least 5 seconds on average.
If that’s how long your call takes, then I see no realistic way of shortening that.
You could try setting up a script that terminates straight away, without giving a return value (or a yeah OK, go on with your stuff, browser response) – and finishes the rest (making the actual API call) afterwards, server-side.

Check if user closed the page in PHP?

I made a chat using PHP and JavaScript chat and there is a disconnect button which removes user from the chat removing him from user list first. But if the user closes browser then he will remain in the user list. How do I check if he left?
This must be done without putting any handles on page closing in JS because if user kills the browser then he will remain in chat.
By the way , JS script always sends a request to the PHP page which constantly checks for new messages in a loop and when there are some, the script prints them out and exits. Then it repeats all over again.
EDIT : How do I make a heartbeat thing in PHP? If a user closes the page the script execution will be terminated therefore we won't be able to check if the user is still connected in the same script.
Sorry, there is no reliable way of doing this, that's the way HTTP was built - it's a "pull" protocol.
The only solution I can think of is that "valid" and logged in clients must query the server in a very small interval. If they don't, they're logged out.
you could send a tiny ajax call to your server every 5 seconds. and users that doesn't do this aren't in the room any more
You answered your own question: if you don't detect a request for new messages from a user over a given length of time (more than a few seconds), then they left the room.
The nature of HTTP dictates that you need to do some AJAX type of communication. If you don't want to listen for the "give me more messages" request (not sure why you wouldn't want to), then build in a heartbeat type communication.
If you can't modify the JS code for some reason, there really is little you can do. Only thing you can do with PHP is to check if there's been for example over 15 minutes from the last activity, the user has left. But this is in no way a smart thing to do – a user might just sit and watch the conversation for 15 minutes.
Only proper way to do is using AJAX polling in set intervals if you want to do it reliably.
You noted that a user polls the server for new messages constantly, can't you use that to detect if user has left?
Maintain a list of active users on the server, as well as the last time they connected to the chat to request new messages.
When a user connects to check for messages update their time.
Whenever your code runs iterate through this list and remove users who haven't connected in too long.
The only failure is that if the number of users in the channel drops to zero, the server wont notice until someone comes back.
To address your edit, you can ignore client termination by using ignore_user_abort.
Using javascript u can do the following :
<script type="text/javascript">
window.onunload = unloadPage;
function unloadPage()
{
alert("unload event detected!");
}
</script>
Make the necessary ajax call on the unloadPage() function to ur PHP Script
Request a PHP script that goes a little something like this, with AJAX:
register_shutdown_function("disconnect_current_user");
header('Content-type: multipart/x-mixed-replace; boundary="pulse"');
while(true) {
echo "--pulse\r\n.\r\n";
sleep(2);
}
This way, you won't constantly be opening/closing connections.
The answers to all the questions asked by the OP are covered in the section in the manual about connection handling:
http://uk3.php.net/manual/en/features.connection-handling.php
No Ajax.
No Javascript.
No keep alives.
C.

Categories

Resources