English 中文(简体)
Javascript threading race condition
原标题:

EDIT: I figured out the answer to the original YUI3 question I posted here, but it led to another one and instead of starting a new thread I thought I d just add it here. Please scroll down for the new question (it s bolded).

Original question: I m having some issues creating a JavaScript countdown timer inside a YUI definition, my guess is something to do with object scoping. Here s my code:

YUI({combine: true, timeout: 10000}).use("node", function (Y) {
    var timer = new function(){};
    Y.augment(timer, Y.EventTarget);
    timer.on( timer:down , function() {
        Y.log( timer down event fired ,  event );
        Y.Lang.later(1000, Y, timer_trigger());
    });
    timer.on( timer:end , function() {
        Y.log( timer end event fired ,  event );
    });

    var timer_from;

    function startTimer(seconds){ // start a coundown from seconds to 0
        timer_from = seconds;
        timer_trigger();
    }

    function timer_display(){
        var mins = Math.floor(timer_from/60);
        var secs = timer_from - mins*60;
        var secsDisp = secs;
        if(secs<10){
            secsDisp =  0  + secs;
        }
        Y.one( #timer ).set( innerHTML , mins +  :  + secsDisp);
    }

    function timer_trigger(){
        Y.log( timer from is:  +timer_from);
        if(timer_from > 0){
            timer_from--;
            timer_display();
            if(timer_from > 0){
                timer.fire( timer:down );
            }
        } else {
            timer.fire( timer:end );
        }
    }

    function initializePage(){
        startTimer(900);
    }


});

The error I m getting is that it doesn t wait the 1000ms like I m asking it to to call timer_trigger() and Safari eventually asks me whether I want to stop running the code. When I do a few seconds after loading the page, the timer is already down to about 3, 4 minutes. I ve also tried using setTimeout but that also produces the same result. Can anyone help? I would really appreciate it!

EDIT: I actually figured out a solution - this came after hours of trying tons of things, but a few more Google searches can sometimes still produce new results/answers (I found the answer on this site, actually).

So apparently my code was creating a race condition, and all I had to do to fix it is this:

setTimeout(function(){ 
    timer_trigger();
}, 1000);

I looked up race conditions, but it s unclear to me what it means in my case, and how the seemingly trivial change to my code fixed the issue I was having. So the original question in answered, but I d like to turn this into the question that arose from the answer.

How does threading in JavaScript work and what cause my race condition, and why did the minor change in code fix the error I had?

最佳回答

Also note that

Y.Lang.later(1000, Y, timer_trigger());

executes timer_trigger immediately and passes the return value to Y.Lang.later. You probably meant

Y.Lang.later(1000, Y, timer_trigger);
问题回答

The problem is not a race condition. The reason the additional call to setTimeout "fixes" your code is because of a logic flaw in timer_trigger. Consider what happens in the case where timer_from is 1 when the function is called. Neither timer:down nor timer:end will be triggered.

function timer_trigger(){
    Y.log( timer from is:  +timer_from);
    if(timer_from > 0){      // Since timer_from is 1, the if block is entered
        timer_from--;        // timer_from is 0
        timer_display();
        if(timer_from > 0){  // This block is not entered, but it has no matching else
            timer.fire( timer:down );
        }
    } else {                 // The matching if block was entered, so this is not
        timer.fire( timer:end );
    }
}

You added this code:

setTimeout(function(){ 
    timer_trigger();
}, 1000);

This causes timer_trigger to be called once more with timer_from already set to 0, allowing the else block to be executed.





相关问题
selected text in iframe

How to get a selected text inside a iframe. I my page i m having a iframe which is editable true. So how can i get the selected text in that iframe.

How to fire event handlers on the link using javascript

I would like to click a link in my page using javascript. I would like to Fire event handlers on the link without navigating. How can this be done? This has to work both in firefox and Internet ...

How to Add script codes before the </body> tag ASP.NET

Heres the problem, In Masterpage, the google analytics code were pasted before the end of body tag. In ASPX page, I need to generate a script (google addItem tracker) using codebehind ClientScript ...

Clipboard access using Javascript - sans Flash?

Is there a reliable way to access the client machine s clipboard using Javascript? I continue to run into permissions issues when attempting to do this. How does Google Docs do this? Do they use ...

javascript debugging question

I have a large javascript which I didn t write but I need to use it and I m slowely going trough it trying to figure out what does it do and how, I m using alert to print out what it does but now I ...

Parsing date like twitter

I ve made a little forum and I want parse the date on newest posts like twitter, you know "posted 40 minutes ago ","posted 1 hour ago"... What s the best way ? Thanx.

热门标签