Asked  8 Months ago    Answers:  5   Viewed   40 times

I am working on a PHP based web app (that i didn't build).

I am running this ajax request:

$.ajax({
    type: 'POST',
    url: "/potato/ajax.php?module=test_module",
    dataType: 'json',
    async: true,
    data: {
            start_ts: that.start_date,
            stop_ts: that.end_date, 
            submitted: true
    },
    beforeSend: function() {
        console.log('Start: ' + new Date().toLocaleString());
        // Show Chart Loading 
        that.qwChart.showLoading({ 
            color: '#00b0f0', 
            // text: that.returnNumWithPrecent(that.progress)
            text: that.qwChartProgress
        });

        // If data div isn't displayed
        if (!that.dataDisplayed) {
            // Show divs loading
            that.showMainDiv();
        } else {
            that.$qwTbody.slideUp('fast');
            that.$qwTbody.html('');
        }
    },
    complete: function(){},
    success: function(result){
        console.log('End: ' + new Date().toLocaleString());

        // Clear timer
        clearInterval(timer);

        // Set progressbar to 100%
        that.setProgressBarTo100();

        // Show Download Button
        that.downloadBtn.style.display = 'inline-block';

        // Insert Chart Data
        that.insertChartData(result);

        // Insert Table Data
        that.insertTableData(result);
    }
});

And for some reason it gets my whole web-app stuck until it returns the data. I know that by default ajax requests are set to 'true' but i added it anyway just to make sure it is. If it is async, it should do the job without getting my web-app stuck, am I right? What can be the problem? Is this a serverside problem? How do I debug this situation?

Edit: By saying "stuck" I mean - when I wait for the response after submitting the ajax call, refreshing the page or opening in parallel other pages (within my web app only) display a white loading screen. Whenever the ajax call returns the data - the white page loads to the requested page.

Data is returned from the PHP file:

<?php 
require_once("/www/common/api/db.php");

    if (!empty($_POST['submitted'])) {

    // error_reporting(-1);
    // Users Array:
    $users      = get_qw_data($start_ts_to_date, $stop_ts_to_date);

    // Summary Array:
    $summary    = get_qw_summary($users);

    // QW Score Array:
    $qws        = get_qw_score($users);

    // Generate CSV Report files
    /* Remove old:*/ 
    if (!is_file_dir_exist($customer))
        create_qw_directory($customer);

    /* Report #1: */ users_apps_google_macros_ma($users['users'], $customer);
    /* Report #2: */ usage_and_qw_summary($summary, $customer);
    /* Report #3: */ qw_score($qws, $customer);
    /* Zip Files: */ zip_qw_files($customer);

    echo json_encode($qws);
}

 Answers

59

PHP sessions are a prime candidate for other requests getting “stuck”, because the session file gets write-locked, so as long as one running script instance has the session open, all others have to wait.

Solution to that is to call session_write_close as soon as possible.


A little extended explanation:

The default storage mechanism for session data is simply the file system. For every active session, PHP simply puts a file into the configured session directory, and writes the contents of $_SESSION to it, so that it can be read back from there on the next request that needs to access it.

Now if several PHP script instances tried to write changed session data to that file “simultaneously”, that would quite obviously have great conflict/error potential.

Therefor PHP puts a write lock on the session file, as soon as one script instance accesses the session - everybody else, other requests (to the same script, or a different one also using the session), will have to wait, until the first script is done with the session, and the write lock gets released again.

Per default, that happens when the script is done running. But if you have longer running scripts, this can easily lead to such “blocking” effects as you are experiencing here. The solution to that is to explicitly tell PHP (via session_write_close), “I’m done with the session here, not gonna write any new/changed data to it from this point on - so feel free to release the lock, so that the next script can start reading the session data.”

The important thing is that you only do this after your script is done manipulating any session data. You can still read from $_SESSION during the rest of the script - but you can not write to it any more. (So anything like $_SESSION['foo'] = 'bar'; would have to fail, after you released the session.)

If the only purpose the session serves at this point (in this specific script) is to check user authentication, then you can close the session directly after that. The rest of the script can then run as long as it wants to, without blocking other scripts from accessing the same session any more.


This isn’t limited to AJAX requests - those are just one of the places where you usually notice stuff like this first, because otherwise you usually don’t have that many requests using the session running in “parallel”. But if you were to f.e. open a long-running script multiple times in several browser tabs, you would notice the same effect there - in the first tab the script will run and do its business, whereas in the following tabs you should notice that those requests are “hanging” as well, as long as the previous script instance holds the write lock on the session.

Wednesday, March 31, 2021
 
Arman
answered 8 Months ago
80

dataType - delete this one.

Add console.log and open console in Your browser

success: function (data) {
   console.log( data );

show Your console, and then You will see why. Maybe an unwanted char or php error

Second thing - there should be if stament like this (I supposed)

if (data == "1") // it is returning string, not integer.

You can also try to use switch case in success.

Wednesday, March 31, 2021
 
CodeCaster
answered 8 Months ago
38

Try this out.

function loadlink(){
    $('#links').load('test.php',function () {
         $(this).unwrap();
    });
}

loadlink(); // This will run on page load
setInterval(function(){
    loadlink() // this will run after every 5 seconds
}, 5000);

Hope this helps.

Thursday, June 3, 2021
 
Asher
answered 5 Months ago
33

If using jQuery 1.5+, you can use jQuery.when() to accomplish this. Something like (shortened the ajax calls for brevity, just pass the objects as you're doing above)

$.when($.ajax("getText.asmx/ws_getText"), 
       $.ajax("getText.asmx/ws_getText")).done(function(a1,  a2){

   // a1 and a2 are arguments resolved for the 
   // first and second ajax requests, respectively
   var jqXHR = a1[2]; // arguments are [ "success", statusText, jqXHR ]
});

You don't know in which order they will return so if you were rolling this by hand, you would need to check the state of the other request and wait until it has returned.

Friday, August 13, 2021
 
d8aninja
answered 3 Months ago
45

To begin using async / await in your Webpack-built code, you need a little help from Babel, specfically the babel-runtime and the babel-plugin-transform-runtime. Fortunately there is a really good writeup on the installation and use of both here on the Babel website. You need Babel to do the following for you:

Automatically requires babel-runtime/regenerator when you use generators/async functions.

I won't repeat what has been written there, however, of particular note is HOW you need to install these, because while their writeup certainly works for most, there is a needed tweak for some AWS Lambda devs who have not needed runtime dependencies before now.

The first part is pretty normal, you need new devDependencies:

npm install --save-dev babel-plugin-transform-runtime

And also you need to tweak your .babelrc file like they describe:

{
  "plugins": [
    ["transform-runtime", {
      "helpers": false,
      "polyfill": false,
      "regenerator": true,
      "moduleName": "babel-runtime"
    }]
  ]
}

But here is the kicker, and this is new to the code above: the babel-runtime is a regular dependencies, not a devDependencies:

npm install --save babel-runtime

These 2 installs and the .babelrc tweaks do SOLVE the async / await problem described above, but it introduces a new problem to the build above: Cannot find module 'babel-runtime/regenerator'.

If you are at all concerned with keeping your Webpack built code small, you are likely also using webpack-node-externals like the above code does. For example, the aws-sdk for JavaScript in Node is very large and is already available in the Lambda environment, so its superfluous to bundle it again. The webpack-node-externals configuration above configures Webpack to ignore ALL the modules in node-modules by default, and there is the root of the new problem. The newly installed babel-runtime is a module that needs to be bundled in the build in order for Lambda to run correctly.

Understanding the problem then, the answer becomes simple: don't use the default configuration. Instead of passing in nothing to webpack-node-externals, configure it like this:

externals: [nodeExternals({
  whitelist: [
    'babel-runtime/regenerator',
    'regenerator-runtime'
  ]
})], // ignore all modules in node_modules folder EXCEPT the whitelist

And that solves both the original async / await problem, and the (possible) new problem you may be encountering if you had no previous dependencies in your build. Hope that helps — happy Lambda awaiting!

Sunday, October 3, 2021
 
Heisenberg
answered 4 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :
 
Share