Ask Dan : More on javascript threading

From time to time, I receive emails from desperate people who want help with their javascript problem. I also receive a lot of emails of people wanting to help me with my “manly problems”. It’s very nice from them to care about me and I take time to reply to each of them but I don’t have that kind of problem for the moment.

Stuart Cooper recently sent me a mail about threading in javascript and I turn to you, javascripters, to find the a solution for his problem. I sent the code on RefactorMyCode for refactorisation and they will automatically show up in the comments of this post (the site is an idea of Marc-André Cournoyer who is a very active developer from Montreal). Don’t be afraid to think outside the box. The solution may be completly different from what is already written.


I am experience trying to create a “cover page” that runs a ping to remote servers.In my code I am using setInterval() to run repeating pings (artificially quickly at the moment, ie 10 seconds rather than 1 min) and display the results to browser. I have built my own XMLHttpRequest module (mainly as a learning exercise) and I don’t believe it to be the source of my ills. I have read through your article and the behaviour of alert() and confirm() fits exactly with what I am seeing when I run the following code :[snippet]

function startup(){

setInterval(”pinger(’live’,0)”,10000);
setInterval(”pinger(’standby’,1)”,10000);
setInterval(”pinger(’dev’,2)”,10000);
setInterval(”pinger(’test1′,3)”,10000);
setInterval(”pinger(’test2′,4)”,10000);
setInterval(”pinger(’test3′,5)”,10000);
setInterval(”pinger(’test4′,6)”,10000);

}

function pinger(server,divit){

console=document.getElementById(’ping_div’ + divit);
console.innerHTML=”;
sendRequest(”../php/ping_sys2.php?target=” + server);

}

[/snippet]

(each server has its own named div to return to)

What I am seeing when I run this is the final pinger response from the callback and nothing else. I since added debugging into my XMLHttpRequest code so that it split out the server response progress.

[snippet]

readyXML=xmlReq.readyState;

[/snippet]

[snippet]

if(readyXML == 3){

data=”Serving …”;

}

if(readyXML == 2){

data=”Sent …”;

}

if(readyXML == 1){

data=”Opening …”;

}

[/snippet]

What I have observed is that when running the setInterval commands as above, all except the final request are “jammed” on readyState = 1 and appropriately responds with “Sending …”

however,

when I do the following (which is messy)

[snippet]

function startup(){

setInterval(”pinger(’live’,0)”,1000);
alert(”something”);
setInterval(”pinger(’standby’,1)”,10000);
alert(”something”);
setInterval(”pinger(’dev’,2)”,10000);
alert(”something”);
setInterval(”pinger(’test1′,3)”,10000);
alert(”something”);
setInterval(”pinger(’test2′,4)”,10000);
alert(”something”);
setInterval(”pinger(’test3′,5)”,10000);
alert(”something”);
setInterval(”pinger(’test4′,6)”,10000);

}

[/snippet]

Each response is absolutely spot on and will continue to generate pings correctly. So in this case the script alert interrupts are forcing the callback request to trigger, whereas without the alerts its only the last request that triggers a callback. I have also tried using artificial timeout loops instead of alerts (which generate the odd browser “script running slowly” message) but to no avail.

At the moment I am almost resigned to having to create individual events (like rollovers, though I would much prefer the ping initialisation to occur window.onLoad()) that trigger the setInterval() … which also seems to work fine.

I am hoping that you may have come across a way of forcing the XMLHttpRequest to respond without forcing alerts or confirms on the user, in the time since the last update to the article.

Commentaires

  1. Casper on RefactorMyCode.com December 6 2007 at 11:45:05

    Javascript threading…

    Are you sure you don’t have a race condition sneaking in there somewhere in sendRequest()? I’d like to see the implementation of that method to really make sure. No global variables or something obvious like that?

  2. Stuart Cooper December 7 2007 at 05:49:10

    Ask and ye shall receive! As this was a learning exercise it may well be my xmlhttprequest that is indeed wrong. The global variable comment triggered in my mind though as you will see below (assuming that this comment formats properly as I have a single global var.

    If this is the cause I shall return to my cave happy and stop mashing my face into the keyboard.

    var xmlReq;

    function sendRequest(url, params, HttpMethod){

    if(!HttpMethod) {
    HttpMethod=”POST”;
    }

    xmlReq=startXMLHTTPRequest();

    if(xmlReq) {

    xmlReq.onreadystatechange=onReadyState;
    xmlReq.open(HttpMethod,url,true);
    xmlReq.send(params);
    }
    }

    function startXMLHTTPRequest(){

    var req=null;

    try {
    req=new ActiveXObject(”Microsoft.XMLHTTP”);
    }
    catch(e)
    {
    req=new XMLHttpRequest()
    }

    return req;

    }

    function onReadyState()
    {
    var readyXML=xmlReq.readyState;
    var data=null;

    if(readyXML == 4){
    if(xmlReq.status == 200) {
    console.innerHTML=”;
    data=xmlReq.responseText;
    }
    else {
    data=xmlReq.status;
    }
    }
    else{
    console.innerHTML=”;

    if(readyXML == 3){
    data=”Serving …”;
    }
    if(readyXML == 2){
    data=”Loading …”;
    }
    if(readyXML == 1){
    data=”Sending …”;
    }
    }

    dataInnerHTML(data);
    }

    function dataInnerHTML(data){

    if(data!=null){
    var newline=document.createElement(”div”);
    console.appendChild(newline);
    newline.innerHTML+=”"+data+”";
    }

    }

  3. Stuart on RefactorMyCode.com December 7 2007 at 06:09:12

    Javascript threading…

    The sendRequest object. Since reading about the global var I have tried removing the “var xmlReq;” line from code and there is no difference in behaviour. The final call still gets executed while the rest stay on “sending”. I can certainly see t…

  4. Stuart Cooper December 7 2007 at 06:10:25

    UPDATE :
    I have taken out the line
    var xmlReq;
    and it hasn’t altered the behaviour.

  5. BK on RefactorMyCode.com December 7 2007 at 10:59:08

    Javascript threading…

    First thing, even though you don’t define the global var, since you probably didn’t add var in front of xmlReq=startXMLHTTPRequest();
    it is still considered a global variable. This means that when you test readyState, you don’t necessarily test th…

  6. Casper on RefactorMyCode.com December 7 2007 at 11:54:04

    Javascript threading…

    Like BK said you have global variables all over the place and this breaks the code. You have to think about what happens when your methods are called concurrently. For example “console” will be overwritten by the latest call, since it’s a global var…

  7. Stuart on RefactorMyCode.com December 10 2007 at 09:18:25

    Javascript threading…

    Thanks for the responses … as I said I wrote my own handler as an exercise in learning. Probably once having done it to understand the process, I should have have switched back to a standard library. I would never have recognised (without your help…

Post a comment

Comments are moderated and innapropriate ones won't be approved. Please respect this public space.