1

I'm writing a Tampermonkey script for a web page and trying to extract data from other pages.
I'm trying to make a function that has a loop inside that goes thru a list, llcList, and retrieves data from ajax method GET, but would like to wait for to finish one request before going to second one.
Bonus would be if I could make it wait some extra time.

What should happen:

  1. send request for a llcList[0]
  2. get return data, process it
  3. wait some time
  4. send new request for a llcList[1]

Is this possible? I tried few methods, every time loop send all requests not a second apart. :

function F_Company_LLC(){
for (i = 0; i < llcList.length;i++) {
        if(llcList[i][2]=="lab"){
            //run function 0
            //break;
        }
        else if(llcList[i][2]=="shop"){
            //run function 1
            //break;
        }
        else{
            F_GET_CompData(llcList, llcList[i][1],i,function(result){
                console.log(result);
            });
        }
}}

function F_GET_CompData(F_GET_CompData_list, CompID, F_GET_CompData_row, callback){
$.ajax({
    method : "GET",
    url: base_link+"/company/edit_company/"+CompID,
    beforeSend: function(){runningRequest++;},
    success: function(data){

  //data processing

        runningRequest--;
    },
    error: function() {console.log("Get_ComData");}
});
callback(runningRequest);}
Brock Adams
  • 90,639
  • 22
  • 233
  • 295
  • In general, avoid ajax calls inside loops. Research alternative solutions where you might make a single ajax call with enough information to update several records, get all records matching multiple companyIds or what ever it is you want to do, etc.. However, I guess a while-loop with complete callbacks or promises to determine when to continue might work? Though what if the call doesn't return and eventually times out, do you continue or not? - I rather would check for a solution which returns multiple records at ones with a single call. – Nope Nov 30 '17 at 17:14
  • I updated code for a point 3. now function LLC_Comp_Timer execute, increment variable i by one and wait for 1second before executing again – StillLearning Nov 30 '17 at 22:54

1 Answers1

1

This is a common scenario. Note that it's often unnecessary to process the calls sequentially though. It's usually adequate to just send context with the ajax calls and piece everything together as it comes in semi randomly, as shown in this answer.


One way to force sequential behavior is to chain calls via the complete function. Here is fully functional code that demonstrates the process. To use, paste it into your browser console while on a Stack Overflow page. :

var listO_pages = ["q/48/", "q/27/", "q/34/", "q/69/", "badpage"];
var numPages    = listO_pages.length;

getPageN (0);  //-- Kick off chained fetches

function getPageN (K) {
    if (K >= 0  &&  K < numPages) {
        let targPage = listO_pages[K];

        $.ajax ( {
            url:            "https://stackoverflow.com/" + targPage,
            context:        {arryIdx: K},  //  Object Helps handle K==0, and other things
            success:        processPage,
            complete:       finishUpRequest,
            error:          logError
        } );
    }
}

function processPage (sData, sStatus, jqXHR) {
    //-- Use DOMParser so that images and scripts don't get loaded (like jQuery methods would).
    var parser          = new DOMParser ();
    var doc             = parser.parseFromString (sData, "text/html");
    var payloadTable    = doc.querySelector ("title");
    var pageTitle       = "Not found!";
    if (payloadTable) {
        pageTitle       = payloadTable.textContent.trim ();
    }
    var [tIdx, tPage]   = getIdxAndPage (this);  // Set by `context` property

    console.log (`Processed index ${tIdx} (${tPage}). Its title was: "${pageTitle}"`);
}

function finishUpRequest (jqXHR, txtStatus) {
    var nextIdx     = this.arryIdx + 1;
    if (nextIdx < numPages) {
        var tPage   = listO_pages[nextIdx];
        //-- The setTimeout is seldom needed, but added here per OP's request.
        setTimeout ( function () {
            console.log (`Fetching index ${nextIdx} (${tPage})...`);
            getPageN (nextIdx);
        }, 222);
    }
}

function logError (jqXHR, txtStatus, txtError) {
    var [tIdx, tPage]   = getIdxAndPage (this);  // Set by `context` property
    console.error (`Oopsie at index ${tIdx} (${tPage})!`, txtStatus, txtError, jqXHR);
}

function getIdxAndPage (contextThis) {
    return [contextThis.arryIdx, listO_pages[contextThis.arryIdx] ];
}


This typically outputs:

Processed index 0 (q/48/). Its title was: "Multiple submit buttons in an HTML form - Stack Overflow"
Fetching index 1 (q/27/)...
Processed index 1 (q/27/). Its title was: "datetime - Calculate relative time in C# - Stack Overflow"
Fetching index 2 (q/34/)...
Processed index 2 (q/34/). Its title was: "flex - Unloading a ByteArray in Actionscript 3 - Stack Overflow"
Fetching index 3 (q/69/)...
Processed index 3 (q/69/). Its title was: ".net - How do I calculate someone's age in C#? - Stack Overflow"
Fetching index 4 (badpage)...
GET https://stackoverflow.com/badpage?_=1512087299126 404 ()
Oopsie at index 4 (badpage)! error  Object {...

-- depending on your Stack Overflow reputation.


Important: Do not attempt to use async: false techniques. These will just: lock up your browser, occasionally crash your computer, and make debug and partial results much harder.

Brock Adams
  • 90,639
  • 22
  • 233
  • 295