简体   繁体   English

在javascript中阻止“等待”功能?

[英]Blocking “wait” function in javascript?

As part of a Javascript project I'm working on, there are some synchronous ajax calls (I guess that makes it "sjax", but I digress) . 作为我正在研究的Javascript项目的一部分,有一些同步的ajax调用(我猜这使它成为“sjax”,但我离题了) I'm now writing a debugging panel which would allow me to test out the site with some artificially simulated network conditions by wrapping $.ajax . 我现在正在编写一个调试面板,它允许我通过包装$.ajax来测试一些人工模拟的网络条件。 Simple things: faking a 500 response etc, and making the ajax calls take much longer. 简单的事情:伪造500响应等,并使ajax调用需要更长的时间。

For the asynchronous calls, it's simple. 对于异步调用,它很简单。 When the real response comes back, add a setTimeout to make it wait for the artificial response time before triggering the callback. 当真实响应返回时,添加一个setTimeout以使其在触发回调之前等待人工响应时间。 However, this doesn't work with the synchronous calls obviously, since setTimeout isn't synchronous. 但是,这显然不适用于同步调用,因为setTimeout不是同步的。

So, is there a way to make a Javascript program perform a blocking wait for a set amount of time? 那么,有没有办法让Javascript程序执行阻塞等待一段时间?

The only thing I could think of would be something like this: 我唯一能想到的就是这样的事情:

function wait(ms) {
    var start = +(new Date());
    while (new Date() - start < ms);
}

Is there a better solution? 有更好的解决方案吗?

(Also, please assume there's a good reason for the blocking ajax calls... :-\\ ) (另外,请假设有一个很好的理由阻止ajax调用...... :-\\

Do not do it on the JavaScript level. 不要在JavaScript级别上执行此操作。 Get a proxy such as Fiddler and set up an AutoResponder to delay the call by a time period. 获取Fiddler等代理并设置AutoResponder以延迟一段时间的呼叫。

If it's just for debugging purposes to have an artificial delay: 如果只是出于调试目的而产生人为延迟:

alert('block me one more time');

There is no reasonable other approach to have a blocking code in ECMAscript. 在ECMAscript中没有合理的其他方法来阻止代码。 Since Javascript is executed in the same thread ("UI thread") which browsers use to render the DOM and to certain other things, the whole show was designed not to block anything. 由于Javascript是在浏览器用来呈现DOM和某些其他东西的同一个线程(“UI线程”)中执行的,因此整个节目被设计为不阻止任何内容。

Of course you can fake it by using a loop, but its a perversion of the show. 当然你可以通过使用循环伪造它,但它是对节目的歪曲。

I figured this code might help 我认为这段代码可能有所帮助

// execute code consecutively with delays (blocking/non-blocking internally)
function timed_functions() 
{
    this.myfuncs = [];
    this.myfuncs_delays = []; // mirrors keys of myfuncs -- values stored are custom delays, or -1 for use default
    this.myfuncs_count = 0; // increment by 1 whenever we add a function
    this.myfuncs_prev   = -1; // previous index in array
    this.myfuncs_cur    = 0; // current index in array
    this.myfuncs_next  = 0; // next index in array
    this.delay_cur     = 0; // current delay in ms
    this.delay_default = 0; // default delay in ms
    this.loop = false;      // will this object continue to execute when at end of myfuncs array?
    this.finished = false;  // are we there yet?
    this.blocking = true;   // wait till code completes before firing timer?
    this.destroy = false;   // <advanced> destroy self when finished


    // handle next cycle execution
    this.next_cycle = function() {
        var that  = this;
        var mytimer = this.delay_default;

        if(this.myfuncs_cur > -1)
            if(this.myfuncs_delays[this.myfuncs_cur] > -1)
                mytimer = this.myfuncs_delays[this.myfuncs_cur];

        console.log("fnc:" + this.myfuncs_cur);
        console.log("timer:" + mytimer);
        console.log("custom delay:" + this.myfuncs_delays[this.myfuncs_cur]);

        setTimeout(function() {
        // times up! next cycle...
        that.cycle(); 

        }, mytimer);
    }



    this.cycle = function() {

        // now check how far we are along our queue.. is this the last function?
        if(this.myfuncs_next + 1 > this.myfuncs_count)
        {
            if(this.loop)
            {
                console.log('looping..');
                this.myfuncs_next = 0;
            }
            else
                this.finished = true;
        }


        // first check if object isn't finished
        if(this.finished)
        return false;

        // HANDLE NON BLOCKING //
        if(this.blocking != true) // blocking disabled
        {
            console.log("NOT BLOCKING");
            this.next_cycle();
        }


        // set prev = current, and current to next, and next to new next
        this.myfuncs_prev = this.myfuncs_cur;
        this.myfuncs_cur  = this.myfuncs_next;
        this.myfuncs_next++; 

        // execute current slot
        this.myfuncs[this.myfuncs_cur]();




        // HANDLE BLOCKING
        if(this.blocking == true)  // blocking enabled
        {
            console.log("BLOCKING");
            this.next_cycle();
        }

        return true;
    }; // END :: this.cycle





    // adders 
    this.add = {
        that:this,

        fnc: function(aFunction) { 
        // add to the function array
        var cur_key = this.that.myfuncs_count++;
        this.that.myfuncs[cur_key] = aFunction;
        // add to the delay reference array
        this.that.myfuncs_delays[cur_key] = -1;
        }
    }; // end::this.add




    // setters
    this.set = {
        that:this, 

        delay:          function(ms)    {  
            var cur_key = this.that.myfuncs_count - 1;
            // this will handle the custom delay array this.that.myfunc_delays
            // add a custom delay to your function container

            console.log("setting custom delay. key: "+ cur_key + " msecs: " + ms);
            if(cur_key > -1)
            { 
                this.that.myfuncs_delays[cur_key] = ms; 
            }

            // so now we create an entry on the delay variable
        },  // end :: this.set.delay(ms)

        delay_cur:      function(ms)        { this.that.delay_cur = ms;         },
        delay_default:  function(ms)        { this.that.delay_default = ms;         },
        loop_on:          function()        { this.that.loop = true; }, 
        loop_off:         function()        { this.that.loop = false; },
        blocking_on:      function()        { this.that.blocking = true; }, 
        blocking_off:     function()        { this.that.blocking = false; },

        finished:           function(aBool) { this.that.finished = true; }
    }; // end::this.set    




    // getters
    this.get = {
        that:this, 

        delay_default: function() { return this.that.delay_default; },
        delay_cur:     function() { return this.that.delay_cur; }
    }; // end::this.get     

} // end ::: timed_functions()

And Test... 并测试......

// // // BEGIN :: TEST // // //

    // initialize
    var fncTimer = new timed_functions;

    // set some defaults
    fncTimer.set.delay_default(1000); // set a default delay between function blocks
    fncTimer.set.blocking_on(); // next timer begins count before code is executed
    fncTimer.set.blocking_off(); // next timer begins count after code is executed
    // fncTimer.set.loop_on(); // when finished start over
    // fncTimer.set.loop_off();


    // BEGIN :: ADD FUNCTIONS (they will fire off in order)
    fncTimer.add.fnc(function() {
        console.log('plan a (2 secs)');
    });
    fncTimer.set.delay(2000); // set custom delay for previously added function


    fncTimer.add.fnc(function() {
        console.log('hello world (delay 3 seconds)');
    });
    fncTimer.set.delay(3000);


    fncTimer.add.fnc(function() {
        console.log('wait 4 seconds...');
    });
    fncTimer.set.delay(4000);
    // END :: ADD FUNCTIONS


    // NOW RUN
    fncTimer.cycle(); // begin execution 


// // // END :: TEST // // //

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM