How to implements Progress bar when doing Ajax request Voluminous db updates - javascript

Good morning,
I have script that updates voluminous data (for exemple 3000Lines) and I have to show to user progress of db updates on progress bar or just the number of lines affected.
I'm working on PHP codeigniter and AJAX
I had an idea to use session codeigniter to store modified variable (incrementation) on the session value on each Loop and call function that give me the session variable as JSON array, but the problem is that the session wouldn't change itself after first update (for exemple: starting with 0 and modified to 20, after that all process on 20)
I don't know how to get better solution to do it. If you can help me it will be really cool.
Thank's to all

PHP won't output anything until the script has fully completed, but you can change that:
ob_implicit_flush(true);
for ($i = 0; $i < ob_get_level(); $i++) {
ob_end_clean();
}
Put this in your PHP script before you start processing your data. As you process parts of your data, output something to tell the AJAX request the progress; for example:
PHP:
$completed_updates = 0;
$last_echoed_progress = 0;
$progress_echo_interval_seconds = 2;
while ($completed_updates < $amount_of_db_updates_to_do) {
do_db_update();
$completed_updates++;
if ($last_echoed_progress + $progress_echo_interval_seconds < time()) {
echo ($completed_updates / $amount_of_db_updates_to_do) * 100;
$last_echoed_progress = time();
}
}
jQuery's .ajax also (by default) won't call the success function with the data until all the data has been received (i.e. script ended), so create a custom XHR object with an event listener that receives the data while the script is still running:
JS:
var last_response_length = 0;
$.ajax({
... // All your other settings
xhr: function() {
var xhr = new XMLHttpRequest(); // Create a custom XHR object
xhr.onprogress = function(data) {
var response = data.currentTarget.response, // Get the output
progress = response.slice(last_response_length) | 0; // Remove old output
$( '#progress-bar' ).val(progress); // Update the progress bar
last_response_length = response.length; // Track where the old data is (so they can be removed when new data is received)
};
return xhr; // IMPORTANT! Return the custom XHR for .ajax to use
},
success: function(response) {
$( '#progress-bar' ).val(100); // All done!
}
});
Obviously modify the code to suit your needs, and experiment a little. Keep in mind that PHP has an execution time limit of 30 seconds by default, so you may need to change this inside your script:
set_time_limit(0);
This allows your script (and only that one) to run without time limits. Put it at the very top. Use caution!

Related

Use PHP variable from another file when ajax is used to fetch php file

This a bit complicated situation I have myself in. I have a PHP file in which I am generating data from DB dynamically. More like when a page is scrolled then data is fetched. So I have two PHP files file1.php and file2.php. file1.php has an ajax that fetches data from file2.php and displays it on its page.
Ajax in file1.php:
$(document).ready(function(){
var limit = 4;
var start = 0;
var action = 'inactive';
function load_posts_data(limit,start)
{
$.ajax({
url : "fetch-message.php",
method : "POST",
data : {limit:limit,start:start},
cache : false,
success : function(data)
{
$('#message_body').append(data);
if(data=='')
action = 'active';
else
action = 'inactive';
}
});
}
if(action=='inactive'){
action = 'active';
load_posts_data(limit,start);
}
$(window).scroll(function(){
if($(window).scrollTop()+$(window).height()>$("#message_body").height()&& action=="inactive"){
action = 'active';
start = start + limit;
setTimeout(function(){
load_posts_data(limit,start);
},100);
}
});
});
Now, file2.php has codes which are extracting data from DB 4 at a time. The problem is that I need to use a variable in file2.php say (variable name, var) which is in file1.php and I have failed to find any solution online. Please help.
You can't directly access PHP variables from Javascript or vice versa ! period. but what you can do instead is while returning the response from the file2.php (where you echo or pass the response according to the ajax call) you can return an array with all the required variable values like this.
return array = [
'data' => $data,
'var1 => $var1,
.
.
'varN' => $varN,
];
and from javascript where you process the response you can simply parse the response, for further reading you can google about :`parsing json in javascript

Am I able to make an AJAX call to a specific function within a PHP file from a JS file

I have a Javascript function that pulls in the users latitude/longitude and stores it in an array for later use. What I'm trying to do is take the users latitude/longitude and run a distance comparison to several other latitude/longitudes which are stored in a database. What I'm trying to do, and I could be thinking about this all wrong, is make a call with AJAX within that Javascript, to a specific function within a PHP file (the function pulls just the latitude/longitude of each related store from the database). Normally, this should be easy, but there are multiple functions within the PHP file so I'm wondering if this can even be accomplished this way.
Thank you in advance for any help you can provide. I'm still new to all of this so your patience is appreciated.
This is the code I have so far (I'm brand new to AJAX so I don't have any AJAX code written yet):
function userPosition() {
navigator.geolocation.getCurrentPosition(function(position) {
var lat = position.coords.latitude;
var lng = position.coords.longitude;
currentPos.push(lat, lng);
}, function(error) {
alert('Error occurred. Error code: ' + error.code);
// error.code can be:
// 0: unknown error
// 1: permission denied
// 2: position unavailable (error response from location provider)
// 3: timed out
});
};
Here's the code within the PHP file:
public function get_closest_location() {
$addresses = array();
$i = 0;
//Get primary address
$addresses[$i]['lat'] = $this->dealer_info['lat_1'];
$addresses[$i]['lng'] = $this->dealer_info['lng_1'];
//Get Dealer Addresses
global $wpdb;
$results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $wpdb->gdp_dealers_addresses WHERE dealerId = %d", $this->dealer_info['dealer_id'] ), ARRAY_A );
foreach($results as $res){
$i++;
$addresses[$i]['lat'] = $res['lat'];
$addresses[$i]['lng'] = $res['lng'];
}
return $addresses;
}
The answer is Yes and No, so the solution is not totally straight forward
As you can only get AJAX to directly run a PHP script and not a function inside it, all you need to do is add some information to the POST data that you send to the PHP script to tell it what function within your PHP library you want to run.
So you add something like this to the posted variables
var params = {.........};
$.ajax({
method: "POST",
url: "some.php",
data: { toRun: 'userPosition', anyData: params }
})
.done(function( msg ) {
alert( msg );
});
Then in your PHP that is the first thing you test for
<?php
// check for existance of all required post variables
switch ($POST['toRun']) {
case : 'userPosition'
// get any other parameters out of POST array you may need
$params = array(.....);
userPosition();
break;
case : 'otherFunction'
...
...
default :
echo 'Huston we have a problem';
This is a basic outline and you will of course have to add some more code to look after passing back data, but this is the basic outline
}
Php essentially runs from top to bottom. Calling the file ftom the browser does just that.
If the file contains function definitions, but no calling code, nothing will be run.
To handle your problem, you need to:
Identify the function to be called
Check it is an allowed function, to avoid malichious code injection
Call the function
To do that, you can send the required function as a get parameter, check it against a whitelist, and call it:
//example.php
function somefunc(){}
function anotherfunc(){}
function privatefunc(){}
function onLoad(){
$func = isset($_GET['func']) ? $_GET['func'] : false;
$allowed = ['somefunc','anotherfunc'];
if(in_array($func, $allowed){
call_user_func($func);
}
}
//call onload function when script is executed
onLoad();
To call a function you would use the correct query string in your ajax request, eg /example.php?func=somefunc
I would recommend you pass a GET parameter to the php script. This would look as follows:
javascript:
$.post( "script.php?action=userPosition", { lat: "2.0123123", long: "2.0319239123" })
.done(function( data ) {
alert( "Data Loaded: " + data );
});
append this to your php file:
if (isset($_GET["action"]) && $_GET["action"] == "userPosition") {
echo get_closest_location($_POST["lat"], $_POST["long"]);
exit;
}
you would need to modify the arguments of the php function obviously, but then this would be all it takes.

Reading file with Javascript into array - can't seem to make it work

I have a simple 2-column csv file that I would like my site to read and ultimately parse into an array. The data is in the following format:
Atlanta Braves, Atlanta_Braves
Baltimore Orioles, Baltimore_Orioles
Boston Red Sox, Boston_Red_Sox
etc.
The file is currently stored in the same location as my html file. I am trying to use an ajax request to pull the data from the file into an array, then parse further such that myArray[0][0] = 'Atlanta Braves'.
Here is my code:
var myArray = [];
$.ajax({
type: 'GET',
url: 'datafilename.csv',
success: function(data){processData(data);}
});
function processData(data){
myArray = data.split('\n');
for (i = 0; i < myArray.length; i++){
myArray[i] = myArray[i].split(',');
}
}
alert(myArray[0][0]);
Unfortunately, the alert only returns 'undefined'. What am I doing wrong here? Any feedback would be appreciated.
$.ajax is an asynchronous function. That means that it won't complete until sometime later, after your other synchronous code has already run. Try adding this:
function processData(data) {
// Your existing code goes here...
alert(myArray[0][0]);
}
This works because processData is only run after the AJAX call has returned. Asynchronous functions basically work like this:
var value = 1;
setTimeout(function() {
value = 2; // This won't happen for about 1 second
console.log(value); // 2
}, 1000); // Run this function in 1 second
console.log(value); // 1. This happens almost immediately, without pause

ajax retrieve huge data from server

My ajax code is
function senddata()
{
var ajaxRequest; // The variable that makes Ajax possible!
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
document.getElementById("showdata").innerHTML=ajaxRequest.responseText;
}
}
ajaxRequest.open("GET", Handler.php?key=" + value, true);
ajaxRequest.send(null);
}
I have huge amount of data that gets retrieved through ajax. Now when i call this function, it takes much time to show data. I want here is that as the data gets retrived, it should be displayed on the screen. No need to show whole retrieved data only when everything is fetched but display data as it gets fetched.
You're going to want to approach this with the same style of thinking as if you were implementing a pagination system.
I cannot see your Handler.php code, so it might make things difficult as we need to edit things in there.
Make Handler.php accept limit and offset or page query var(s)
Add the appropriate code in your PHP to handle that (and the case where none are provided, don't just sent everything! default limit to 10 and offset to 0.)
Functionalize your ajax request and make it paginate:
function getdata(limit, offset)
{
limit = limit || 10;
offset = offset || 0;
var ajaxRequest; // The variable that makes Ajax possible!
// Create a function that will receive data sent from the server
ajaxRequest.onreadystatechange = function()
{
if(ajaxRequest.readyState == 4)
{
document.getElementById("showdata").innerHTML=ajaxRequest.responseText;
// make Handler.php send 'end' when no results have been returned
if (ajaxRequest.responseText && ajaxRequest.responseText != 'end') {
getdata(limit, offset + limit);
}
}
}
ajaxRequest.open("GET", Handler.php?key=" + value + '&limit=' + limit +
'&offset=' + offset, true);
ajaxRequest.send(null);
}
getData();
Just make sure Handler.php sends end when there is no more data.

Storing progress in session variable

I am trying to implement a progressbar when a user executes find request in my web application(php/js/html).
When the user executes the find request, application executes php script using ajax, this script periodically stores its progress in session variable.
What I tried to do is to poll the server with another ajax request to ask for the session progress variable, but the variable does not exist.
Why is this happening, is this not possible using php sessions?
Thanks
JS logic:
// When the user selects interested object, find it on the server
$(document).on('change', '#findStreamer', function()
{
$streamerId = $(this).val();
$streamerName = $('#findStreamer option[value="'+$streamerId+'"]').text();
console.log('findDB', $streamerId, $streamerName);
addProgressBar();
getProgress();
$.ajax({
type: 'POST',
url: 'serverlink/findobject',
data: {
findChannel: $streamerName,
checkOnline: true
},
success: function(response)
{
$streamData = JSON.parse(response);
$('#streamPreview').remove();
// $('#findPanelToolbar').before($streamData.streamerView);
console.log($streamData);
}
});
});
function getProgress()
{
$.ajax({
type: 'POST',
url: 'serverlink/getprogress',
complete: getProgress,
timeout: 60000,
success: function(response)
{
$progresValue = response;
updateProgressBar($progresValue);
}
});
}
Server logic:
public function action_findobject()
{
$_SESSION['percentage'] = 0;
if(!(Input::is_ajax()))
{
$response = Response::forge();
$response->set_status(400);
return $response;
}
// Long actions //
$_SESSION['percentage'] = 10;
// Long actions //
$_SESSION['percentage'] = 45;
// Long actions //
$_SESSION['percentage'] = 100;
return $Outputdata;
}
public function action_getprogress()
{
return $_SESSION['percentage'];
}
I think you need create php script, which will execute some tot big part of process and send json with %. Also percents need to be stored in session. In browser you will invoke ajax till get some error or result 100%. After you got answer from server, if percents<100 -> show new percent line to customer and do the same request to server..
Not a solution so I'll wikify this but to answer the question, "is this not possible using php sessions?"... looks like a no - or at least not in the code's current form. You would have to delegate the resource-intensive operation to another process somehow as the following simple test suggests that the first operation is blocking.
<?php // sleep.php
session_start();
$_SESSION['foo'] = gmdate('r');
sleep(10);
<?php // test.php
session_start();
echo !isset($_SESSION['foo'])
? 'session not set'
: $_SESSION['foo'];
Test:
Browse /sleep.php which sets some value in the session then waits for 10 seconds (arbitrary) to mimic some exhaustive program/execution. Open a new tab inside of the 10 second delay and browse /test.php.
Expected Result:
/test.php immediately returns the date that was set by /sleep.php
Actual Result:
/test.php request hung/waited until /sleep.php request had finished.
I managed to solve this problem using caching in a file, dont know how optimal that is, but thanks to everyone for your suggestions!

Categories