1

I've tried putting gm_xmlhttprequest inside a while loop but the code executes synchronously. Is it possible to make it execute asynchronously, one at a time?

frosty
  • 2,559
  • 8
  • 37
  • 73
  • `but the code executes synchronously` - don't set `synchronous:true` - the default behaviour is *asynchronous*, so it's only *synchronous* because you've set `synchronous:true` in the `details` argument – Jaromanda X Aug 24 '18 at 00:05
  • oh wait .... `asynchronously, one at a time` ... erm ... have you mixed up the words `asynchronous` and `synchronous` - if the requests are made asynchronously, they'll all "happen at once" (not really but thre's no waiting) - what you want (don't do it though) is for the requests to happen *synchronously* so you can do one at a time ... but don't do that ... embrace asynchrony - you can still do one at a time asynchronously – Jaromanda X Aug 24 '18 at 00:08
  • @JaromandaX Er...I think you have it backwards. Synchronous is existing or occurring at the same time. Asynchronously, is one at a time. Just to confirm, I googled it, and that's what google said. – frosty Aug 24 '18 at 00:10
  • 1
    add `synchronous:true` to the details object you pass to `gm_xmlhttprequest` and your code will behave as you wish - clearly the makers of greasemonkey are playing tricks on you when setting `synchronous:true` makes the request *asynchronous* - but you know programmers, always like to have the last laugh - I'm sure [MDN also are deliberately misleading you](https://developer.mozilla.org/en-US/docs/Glossary/Asynchronous) – Jaromanda X Aug 24 '18 at 00:16
  • in programming, think of synchronous as *sequential* - i.e. the code runs sequentially in the order it is written, each statement *waits* for the previous statement to complete before executing ... whereas in asynchronous code parts of the code can run *later*, when some external event or result is available - so, it's non-sequential (that's what callbacks are all about, and any other asynchronous patterns of code you see are just glorified callbacks) – Jaromanda X Aug 24 '18 at 00:20
  • @JaromandaX I am very confused. Are you saying the meaning of synchronous and asynchronous in programming are the opposite of the words themselves means when used outside of programming? – frosty Aug 24 '18 at 00:24
  • no, I'm saying they mean exactly the same thing, it's your interpretation that is wrong ... actually, that's probably not fair ... the meanings in javascript have different context - trust me - you want *synchronous* requests (though, you don't really want that because of the impact in the UI) - if, as is one of the main stipulations for questions on SO, you included your code (or the part you are dealing with) then I could show you exactly how to do what you want, neatly and asynchronously – Jaromanda X Aug 24 '18 at 00:25
  • @JaromandaX I've edited parts of my codes above. Basically, I want to add the links to a long link list if they matches. But since the code runs at the same time, I only get the last link added. – frosty Aug 24 '18 at 00:36
  • @JaromandaX No, that's only part of the code. The link variable is of different links every time it pass through the while loop. – frosty Aug 24 '18 at 00:40
  • fair enough, answer added – Jaromanda X Aug 24 '18 at 00:42

1 Answers1

1

simplest change to your code would be as follows

function doXHR(counter) {
    if (counter < count) {
        var GoToURL = link;
        GM_xmlhttpRequest({
            method: "GET",
            url: GoToURL,
            onload: function(response) {
                if (response.finalUrl.match(/true$/)) { 
                    longList = longList + link; 
                }
                doHXR(counter+1);
            }
        });
    }
}
doXHR(0);

i.e. in the onload, run the next iteration ... this will result in the requests being made sequentially

If you need to run this code, then when all requests are finished continue on to do something else

function doAllXHR(count, callback) {

    function doXHR(counter) {
        if (counter < count) {
            var GoToURL = link;
            GM_xmlhttpRequest({
                method: "GET",
                url: GoToURL,
                onload: function(response) {
                    if (response.finalUrl.match(/true$/)) { 
                        longList = longList + link; 
                    }
                    doHXR(counter+1);
                }
            });
        } else {
            callback('done');
        }
    }
    doXHR(0);
}

doAllXHR(20, function(result) {
    console.log(result);
    // and continue with whatever it is you do
});
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • I tried this code but it only process the first few links, and then stop processing the rest of the links. – frosty Aug 24 '18 at 05:40
  • To be more precise, the "counter" goes from 0 to 1, and then it stops. – frosty Aug 24 '18 at 05:45
  • and an `onerror` handler - you're probably getting an error - or maybe, `response.finalUrl` is `undefined` - the "Browser console" (ctrl+shift+j) may have an error message for you – Jaromanda X Aug 24 '18 at 05:49
  • There's no error in the console. But when I tried to alert the "counter" it just alerts 0, then 1, and then it just stops. – frosty Aug 24 '18 at 05:51
  • Wait...there's actually some errors in the console. – frosty Aug 24 '18 at 05:54
  • did you see my typo? `doHXR(counter+1);` that's incorrect - it should be `doXHR(counter+1);` – Jaromanda X Aug 24 '18 at 05:54
  • Yeah I fixed that a while ago. Right now I'm just getting a few errors in console. The first one is Uncaught TypeError: Cannot read property 'length' of null – frosty Aug 24 '18 at 05:55
  • well, that's to do with code you *haven't posted* - because you don't ever try to access `.length` property in any code you've posted - perhaps, since you didn't really post much about the code you've got, you've not implemented my suggestion correctly – Jaromanda X Aug 24 '18 at 06:02
  • Never mind. I was calling the function inside an if statement, and it passed on the first and second attempt, but not the third, so the function stopped calling on the third loop. I fixed it. Thanks, your function works perfectly. – frosty Aug 24 '18 at 06:08
  • Wait. This code. I've tried to add the links to cookies inside the onload function. But it only adds the last link over and over again. I think this code is still running at the same time... – frosty Aug 24 '18 at 06:35
  • impossble ... `doXHR(1)` won't be executed until the load event (i.e. completed) of `doXHR(0)` – Jaromanda X Aug 24 '18 at 06:42
  • Okay. I've edited the code. The "checkIfAlreadyDidHits" above and below both alerts different links every time, but the one inside the onload function alerts the same link every single time, and it only executes AFTER the "checkIfAlreadyDidHits" alerts both above AND below. – frosty Aug 24 '18 at 06:56
  • Sorry, you can un-accept or whatever, but I'm not going to rewrite the answer to fit your new unformatted and impossible to read code - please unaccept this answer and I'll delete it – Jaromanda X Aug 24 '18 at 06:58
  • This is why I used less code the first time, so you would have an easier time to read it. You know what? I'll write a shorter example version, and then let you take a look at it. Is that okay? – frosty Aug 24 '18 at 07:00
  • Never mind. I more or less debugged it and now it's working. – frosty Aug 24 '18 at 08:31