Wait until flag=true

2019-01-04 02:08发布

I have javascript function like this:

function myFunction(number) {

    var x=number;
    ...
    ... more initializations
    //here need to wait until flag==true
    while(flag==false)
    {}

    ...
    ... do something

}

The problem is that the javascript is stuck in the while and stuck my program. so my question is how can I wait in the middle of the function until flag is true without "busy-wait"?

9条回答
再贱就再见
2楼-- · 2019-01-04 02:25
function waitFor(condition, callback) {
    if(!condition()) {
        console.log('waiting');
        window.setTimeout(waitFor.bind(null, condition, callback), 100); /* this checks the flag every 100 milliseconds*/
    } else {
        console.log('done');
        callback();
    }
}

Use:

waitFor(() => window.waitForMe, () => console.log('got you'))
查看更多
霸刀☆藐视天下
3楼-- · 2019-01-04 02:28

Javascript is single threaded, hence the page blocking behaviour. You can use the deferred/promise approach suggested by others, but the most basic way would be to use window.setTimeout. E.g.

function checkFlag() {
    if(flag == false) {
       window.setTimeout(checkFlag, 100); /* this checks the flag every 100 milliseconds*/
    } else {
      /* do something*/
    }
}
checkFlag();

Here is a good tutorial with further explanation: Tutorial

EDIT

As others pointed out, the best way would be to re-structure your code to use callbacks. However, this answer should give you an idea how you can 'simulate' an asynchronous behaviour with window.setTimeout.

查看更多
仙女界的扛把子
4楼-- · 2019-01-04 02:30

For iterating over ($.each) objects and executing a longish-running operation (containing nested ajax sync calls) on each object:

I first set a custom done=false property on each.

Then, in a recursive function, set each done=true and continued using setTimeout. (It's an operation meant to stop all other UI, show a progress bar and block all other use so I forgave myself for the sync calls.)

function start()
{
    GlobalProducts = getproductsfromsomewhere();
    $.each(GlobalProducts, function(index, product) {
         product["done"] = false;
    });

    DoProducts();
}
function DoProducts()
{
    var doneProducts = Enumerable.From(GlobalProducts).Where("$.done == true").ToArray(); //linqjs

    //update progress bar here

    var nextProduct = Enumerable.From(GlobalProducts).Where("$.done == false").First();

        if (nextProduct) {
            nextProduct.done = true;
            Me.UploadProduct(nextProduct.id); //does the long-running work

            setTimeout(Me.UpdateProducts, 500)
        }
}
查看更多
登录 后发表回答