mwebber
mwebber

Reputation: 386

How to make for loop with ajax not freeze my Firefox Extension?

I make firefox extension which does ajax calls every one minute.

what the script does, is looks through LI elements on given page and returns it page/position if match is found

Here is part of my problematic code:

var item_name = 'test';
var items_per_row = 8;
var last_index;
var last_status;
var x = new XMLHttpRequest();
x.open('GET', 'http://example.com/script.php?page=0', false);
x.onload = function(e) {
    var doc = document.implementation.createHTMLDocument("document"); doc.documentElement.innerHTML = x.responseText;
    var bool = $("div.l1 p",doc).filter(function() { return $(this).text() == item_name});
    last_index = $("div.l1 p",doc).index(bool)+1;
    if(bool.length){ // if match found on first page
        inspector4pda.cScript.position = bool.length+""+Math.ceil(last_index/items_per_row)+""+("0" + last_index).slice (-2);
    } // Main page
    else // Other pages
    {
        var found = false;
        jQuery.ajaxSetup({async:false});
        for(var i=1;i<15;i++)
        {
            $.get( "http://example.com/script.php?page="+i, function( data ) { 
                    var doc2 = document.implementation.createHTMLDocument("document2");
                    doc2.documentElement.innerHTML = data;
                    var bool = $("div.l1 p",doc2).filter(function(index) { return $(this).text() == item_name});
                    last_index = $("div.l1 p",doc2).index(bool)+1;
                    if(bool.length == true){ 
                        found=true;
                        last_status = $("div.l1 p",doc2).eq(last_index-1).parents("li").find(".l2 p").attr("class").split(/\s+/)[0];
                    }
                });
            if(found){ 
                if(last_status == "g-mem"){ inspector4pda.cScript.position = "Плат"; break; }
                if(last_status == "g-dis"){ inspector4pda.cScript.position = "Диск"; break; }
                if(last_status == "g-pri"){ inspector4pda.cScript.position = "Прив"; break; }
                if(last_status == "g-vid"){ inspector4pda.cScript.position = i+1+""+Math.ceil(last_index/items_per_row)+""+("0" + last_index).slice (-2); break; }
            }
        }
        jQuery.ajaxSetup({async:true});
        if(!found) { 
            inspector4pda.cScript.position = "OFF"; 
        }
    }
}
x.send();

with "jQuery.ajaxSetup({async:false}); it works, but freezes for several seconds(because waits all $.get calls synchronously) which i don't want. if i remove it the problem is gone, but the script doesn't work...(i want the $.get calls to execute after each other)

so my question is is there a way (callback or something) to tell to my

 if(found)

to wait all $.get calls and then do its work, without using async:false and freezing the browser?

Thanks!

Upvotes: 0

Views: 115

Answers (2)

Blagoh
Blagoh

Reputation: 1235

This should work, although I mixed let in here in order to hoise theUrl if you use var in that situation it will execute the same URL over, I think.

What I did here was set-up a counter of sorts.

var item_name = 'test';
var items_per_row = 8;
var last_index;
var last_status;
var x = new XMLHttpRequest();
x.open('GET', 'http://example.com/script.php?page=0', false);
x.onload = function(e) {
    var doc = document.implementation.createHTMLDocument("document"); doc.documentElement.innerHTML = x.responseText;
    var bool = $("div.l1 p",doc).filter(function() { return $(this).text() == item_name});
    last_index = $("div.l1 p",doc).index(bool)+1;
    if(bool.length){ // if match found on first page
        inspector4pda.cScript.position = bool.length+""+Math.ceil(last_index/items_per_row)+""+("0" + last_index).slice (-2);
    } // Main page
    else // Other pages
    {
        var found = false;
        jQuery.ajaxSetup({async:true});
    var requestCompletions = {};
        for(var i=1;i<15;i++)
        {
            requestCompletions['http://example.com/script.php?page='+i] = 0;

    }
        for(var i=1;i<15;i++)
        {
        let theUrl = "http://example.com/script.php?page="+i;
            $.get( theUrl, function( data ) {

                    var doc2 = document.implementation.createHTMLDocument("document2");
                    doc2.documentElement.innerHTML = data;
                    var bool = $("div.l1 p",doc2).filter(function(index) { return $(this).text() == item_name});
                    last_index = $("div.l1 p",doc2).index(bool)+1;
                    if(bool.length == true){ 
                        found=true;
                        last_status = $("div.l1 p",doc2).eq(last_index-1).parents("li").find(".l2 p").attr("class").split(/\s+/)[0];
                    }
            // mark this request completed and see if all requests completed:
            delete requestCompletions[theUrl];
            if (Object.keys(requestCompletions).length == 0) {
                // ok all requests done:
                        if(found){ 
                            if(last_status == "g-mem"){ inspector4pda.cScript.position = "Плат"; break; }
                            if(last_status == "g-dis"){ inspector4pda.cScript.position = "Диск"; break; }
                            if(last_status == "g-pri"){ inspector4pda.cScript.position = "Прив"; break; }
                            if(last_status == "g-vid"){ inspector4pda.cScript.position = i+1+""+Math.ceil(last_index/items_per_row)+""+("0" + last_index).slice (-2); break; }
                        }
            } 

                });
        }
        jQuery.ajaxSetup({async:true});
        if(!found) { 
            inspector4pda.cScript.position = "OFF"; 
        }
    }
}
x.send();

Upvotes: 2

the8472
the8472

Reputation: 43052

You can simply put a counter and increment it with each callback, then have the callback that meets the target number call the followup action.

Alternatively you can warp each ajax call into a promise and use Promise.all(...ajaxPromises).then(followupAction)

Upvotes: 2

Related Questions