I have a rails app where in my application.js I have a setInterval() and inside of it an AJAX call that send a post request every minute to my controller in order to perform a create action.
setInterval(function(){
$.ajax({
type: "POST",
url: "/post",
data: { parameter: value },
success: function (data) {
//some logic
}
});
}, 60000);
My problem is that if the client refresh its page every 30 sec (for exemple) the setInterval() set for 1 minute will never be triggered.
Is there a way to make my javascript code not dependent of any page refresh so that if different users arrive at different time they get to see the same thing. I guess it has to do with cookies or local storage but I have no idea how to implement that in a reliable way.
In other word, I would like my js code to be run server side without being disrupted by page refreshes or client request which keep reseting my code.
Thank you for your guidance.
You can use https://github.com/javan/whenever
every 1.minute do # 1.minute 1.day 1.week 1.month 1.year is also supported
runner "MyModel.some_process"
rake "my:rake:task"
command "/usr/bin/my_great_command"
end
Related
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.
So i have the below code to add the additional data to any ajax request made by my app, but the problem is it's working only first time when the page loads , as the application is single page ajax based application , i want to use the updated variable value inside ajaxSetup to make sure all the things work as expected but somehow it takes the old value , i know ajaxSetup setups the data for ajax call on page load. here is what my ajaxSetup looks alike:
var token = 'b62e0352ae559ae1d1e98f0d26604630'; // this variable updates every minute.
setInterval({
var token = $('meta[name=token]').attr('content'); // the updates the token variable every 1 minute
},1000*60*1);
$.ajaxSetup({
data: {
token: token
}
});
as there is predefined token, after every minute it does update , and i just want to pick the updated value of meta tag and then use it for any ajax request made on page.
if there is any another way or correction of this code it will be very helpful.
Request the token when needed so it will be up to date each time.
$.ajaxSetup({
data: {
token: function(){
return $('meta[name=token]').attr('content');
}
}
});
When the user presses the 'Process' button on my application, I would like the application to trigger an AJAX request and then immediately redirect the user to another screen without waiting for the results of the AJAX request. I believe I have coded it appropriately but I notice that the screen is waiting for the AJAX to finish before redirecting. Am I missing something below?
$('#process-btn').on('click', function()
{
// disable the process & cancel buttons to prevent
// double submission or interruption
$('#cancel-btn').addClass('disabled');
$(this).addClass('disabled');
// trigger the AJAX require to process the uploaded file on the server side
$.ajax({
url: $('#form').attr('action'),
type: 'post',
data: $('#form').serialize(),
success: function() {
//on success
}
});
// redirect the user to view list
// this line is not being called immediately -
// this is being called only after AJAX returns
window.location.replace( www_root + 'Home/index' );
});
Because the button you have this handler hooked to is a submit button for a form (per your comments) and you aren't preventing the default behavior of that button, then the form submit will happen immediately and when the submit returns, it will change the page regardless of what your code tries to do.
So, the issue is that the returned form submit was overcoming what your code was trying to do.
You may be living a little dangerously by redirecting before your ajax call has finished. It's possible the browser could drop the ajax connection before the TCP buffers had actually been sent as TCP often has a small delay before sending buffers in order to collect consecutive data into common packets. It would be much safer to either redirect after a short timeout or redirect on the complete event which will be called regardless of ajax success.
If you really want to do the redirect BEFORE the ajax call has completed, you can experiment with the timeout value (shown here as set to 500ms) in this code to see what works reliably in multiple browsers:
$('#process-btn').on('click', function(e) {
// prevent default form post
e.preventDefault();
// disable the process & cancel buttons to prevent
// double submission or interruption
$('#cancel-btn').addClass('disabled');
$(this).addClass('disabled');
// trigger the AJAX require to process the uploaded file on the server side
$.post($('#form').attr('action'), $('#form').serialize());
// redirect the user to view list
// this being called after a short delay to "try"
// to get the form ajax call sent, but not "wait" for the server response
setTimeout(function() {
window.location.replace( www_root + 'Home/index' );
}, 500);
});
Also, note that I've added an e.preventDefault() and added the e argument to the event handler to make sure the form is not posted by default, only by your ajax code.
And, the timeout time is set here to 500ms. What you need is enough time for the TCP infrastructure in the host computer to send all your form data before you start the redirect. I see a mention of a "file upload" in your comments. If this form is actually uploading a file, that could take way, way longer than 500ms. If it's just sending a few form fields, that should go pretty quickly assuming there are no connection hiccups.
Caveat: Doing it this way is not the 100% reliable way of getting data to your server. There can easily be some conditions where it takes longer than usual just to do a DNS lookup before connecting with your server or your server could momentarily take longer to respond to the initial connection before data can be sent to it. The only 100% reliable way is to wait until the ajax call has succeeded as mentioned elsewhere.
You could perhaps have the best of both worlds (reliability + fast response) if you changed the way your server processes the ajax call so that as soon as it has received the data, it returns a successful response (e.g. in milliseconds after receiving the data) and then after it has sent back the successful response so the browser can then reliably do its redirect, it takes it's 2-3 minutes to actually process the data. Remember, you don't gave to wait until you are done processing the request to return a response. Then, you know that the server has received the data, but the browser doesn't have to wait for the processing time. If you don't always want this ajax call to work that way, you can pass an argument to the ajax call to instruct the server whether you want the fast response or not.
Why not try this:
$.ajax({
url: $('#form').attr('action'),
type: 'post',
data: $('#form').serialize(),
success: function() {window.location.replace( www_root + 'Home/index' );}
});
I have a Python based flask web application which shows some SQL information on a html page.
This page is semi-realtime, it gets refreshed every 15 minutes with a simple html refresh:
<META HTTP-EQUIV="refresh" CONTENT="9000">
This works fine as long as the connection is up, there are no internal code errors.
Now I don`t want to have to manually refresh the page once it cannot refresh the page correctly for whatever reason. (connection, internal error).
Is it possible to have a webpage that keeps refreshing every fixed period of time regardless on whether the last refresh was succesfull.
Currently the html page contains no Javascript or the like, just plain html which is generated by Flask built-in template engine Jinja2.
Is it maybe possible to load the webpage completely first than check if it was successful and then refresh?
If you get the a javascript library such as jQuery, you can do this with the asynchronous Ajax functions. Here is an example of how you can replace your <body> content every 15 minutes if it is successfully loaded:
function update_site() {
$.ajax({
url: "/my/page/url/",
dataType: "html",
cache: false,
success: function(data) {
// Replace body with loaded site. You can do more checks here to check
// if the fetched content is all there.
var body_html = /^.*<body>(.*)<\/body>.*$/g.exec(data)[1];
$('body').html(body_html);
},
error: function(data) {
// Couldn't load site.
}
});
}
// Run every 15 minutes.
window.setInterval(function() {
update_site();
}, 15*60*1000);
You could implement some javascript to check the connection when a button is pressed. You could use the navigator.onLine property which should work with all major browsers.
Read more here:
http://www.w3schools.com/jsref/prop_nav_online.asp
should try this
function update_site() {
$.ajax(
{
url: "/my/page/url/",
dataType: "html",
cache: false,
success: function(event)
{
var update_html = /^.*<body>(.*)<\/body>.*$/g.exec(event)[1];
$('body').html(update_html);
},
error: function(event) {
}
});
}
// Run every 10 minutes.
window.setInterval(function() {
update_site();
// To refresh site every 15 min
}, 15000000);
I'm following the example below to continuously refresh a div with a mysql table.
http://techoctave.com/c7/posts/60-simple-long-polling-example-with-javascript-and-jquery
I'm using the complete and timeout parameter of ajax to refresh the div instead of using setinterval and settimeout.
The problem I'm having is that the returning data can include links and these are not working when clicked. I believe the problem could be that the div is constantly refreshing and thus I the click is ignored. How do you allow links within a refreshing div? It works with setinveral and settimeout but I want to use long polling to allow real time updates.
Here is my code.
// get page url variables
function getUrlVars() {
var vars = {};
var parts = window.location.href.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(m,key,value) {
vars[key] = value;
});
return vars;
}
// set var for parent id to scroll to
var tid = getUrlVars()["tid"];
var pid = getUrlVars()["pid"];
(function poll(){
// get latest page
$.ajax({
url: "ajax.tickets_details.php?tid=" + tid,
type: 'GET',
cache: false,
success: function(html) {
// print results from get in div
$("#ticket_updates").html( html );
},
complete: poll,
timeout: 30000
});
})();
Thanks!
I've just read that tutorial and it's based on false information.
this tutorial says:
This means our poll function won't get called again until both the
ajax call is complete and (at-least) thirty (30) seconds have passed.
this isn't true. If your request returns in < 30s it will fire again immediately, thus causing your problem. The Actual definition of timeout is:
Set a timeout (in milliseconds) for the request. This will override
any global timeout set with $.ajaxSetup(). The timeout period starts
at the point the $.ajax call is made; if several other requests are in
progress and the browser has no connections available, it is possible
for a request to time out before it can be sent. In jQuery 1.4.x and
below, the XMLHttpRequest object will be in an invalid state if the
request times out; accessing any object members may throw an
exception. In Firefox 3.0+ only, script and JSONP requests cannot be
cancelled by a timeout; the script will run even if it arrives after
the timeout period.
So this means if the request takes more than 30s it will cancel the waiting handler only (not the call itself, this will continue but the javascript handler will go out of scope).
There is even a comment highlighting this flaw:
I'd find a new tutorial as that one appears to be talking nonesense. This technique is not doing "server push" at all. Only web sockets can push from the server. HTTP 1.1 does not support any server push methods at all.