0

I have a jQuery script that makes an Ajax call to a PHP file (process.php) to retrieve the status of a database (The upload.php and import.php parts are working fine and not relevant here I would say), and I use javascript setInterval() to return the progress status value every second. Here is my jQuery script.

jquery.js
 $(document).ready(function(){
  var clear_timer;
  $('#sample_form').on('submit', function(event){
   event.preventDefault();
   $.ajax({
    url:"ajax/upload.php",
    method:"POST",
    //Additional Ajax parameters here
    success:function(data){
     if(data.success){    
        start_import();
        clear_timer = setInterval(get_imported_data, 1000);
     }
     if(data.error){
     //Error case code here
     }
    }
   })
  });
  function start_import(){
   $.ajax({
    url:"ajax/import.php",
    success:function(){
    }
   })
  }
  function get_imported_data(){
   $.ajax({
    url:"ajax/process.php",
    success:function(data){
     var total_data = $('#total_data').text();
     var initial_rows = $('#initial_rows').text();
     var width = Math.round(((data-initial_rows)/total_data)*100);
     if(width >= 100){
     clearInterval(clear_timer);
     //Extra ajax parameters here
     }
    }
   })
  }
 });

Here is my process.php script

session_start();
try{
    $pdo_options[PDO::ATTR_ERRMODE] = PDO::ERRMODE_EXCEPTION;
    $dbuser = "user";
    $dbpass = "password";
    $dbhost ="mysql:host=my_host;dbname=my_db;charset=utf8mb4";
    $connect = new PDO($dbhost, $dbuser, $dbpass, $pdo_options);
}catch(Exception $e){       
    //Some Error handling here
}
$user_table = $_SESSION['user_table'];
$query = "SELECT * FROM $user_table";
$statement = $connect->prepare($query);
$statement->execute();
echo $statement->rowCount();

The progressbar looks like this if anybody is interested

Progressbar

The problem I have is that if I use session_start(); in the PHP file, the progress bar only displays at the very end of the process. If I remove session_start() and use static variables or constants, the progress bar displays correctly during all the process. I've searched extensively on various forums and can't find any posts like this that discuss the eventual link between session_start(); (in PHP) and setinterval(function(),delay); (in JS). The problem is that I need to be able to use a session variable in order to choose a table selected by the user. Any ideas on how to deal with this issue?

3
  • use the session, but do session_write_close() as soon as possible Commented Jun 25 at 22:05
  • Thanks a lot IT goldman. Could you explain what this does in this context? Commented Jun 25 at 22:12
  • session_start open the session file with a access lock, then if you start more scripts with session_start, the second waits that the first script releases the lock. and this is released at the end of the script or with session_write_close. Commented Jun 25 at 22:42

1 Answer 1

0

Thanks for the inputs. I found the problem. The issue was that the Ajax script was launching several simultaneous sessions through the three scripts (upload.php, import.php, and process.php) in order to retrieve the variables entered by the user.

This works fine until the import.php script (which imports data into the database) runs to completion, and at the same time, process.php captures the progress of the process.

I read in this post that

"The problem with running concurrent AJAX requests that manipulate session data is that PHP by default only allows one script to have access to the session at a time: from the time it calls session_start() to the time it exits or otherwise calls session_write_close(). When you have multiple AJAX requests happening simultaneously that need to write to the session, they can step on each other and you end up with incomplete data."

As a result, process.php waited for import.php to finish before continuing.

So, an alternative solution is needed.

This could be either one of both options

1 - writing the user's information to an external database (or a file or other location) in order to retrieve it in process.php without a session variable,

2 - simply passing the parameters retrieved from the user via ajax POST or GET.

I propose to illustrate method number 2, which allowed me to make the progress bar work again (Make the progress bar great again xD).

jquery.js
 $(document).ready(function(){
  var clear_timer;
  $('#sample_form').on('submit', function(event){
   event.preventDefault();
   $.ajax({
    url:"ajax/upload.php",
    method:"POST",
    //Additional Ajax parameters here
    success:function(data){
     if(data.success){    
        start_import();
        //Retrieve a new user variable and push it in get_imported_data function
        clear_timer = setInterval(function() { get_imported_data(data.selected_country); }, 1000);
     }
     if(data.error){
     //Error case code here
     }
    }
   })
  });
  function start_import(){
   $.ajax({
    url:"ajax/import.php",
    success:function(){
    }
   })
  }
  //Retrieve the variable. Send post data to the script and we don't need the Session variable anymore
  function get_imported_data(selected_country){
   $.ajax({
    url:"ajax/process.php",
    data: { user_selected_country: selected_country },
    success:function(data){
     var total_data = $('#total_data').text();
     var initial_rows = $('#initial_rows').text();
     var width = Math.round(((data-initial_rows)/total_data)*100);
     if(width >= 100){
     clearInterval(clear_timer);
     //Extra ajax parameters here
     }
    }
   })
  }
 });
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.