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

时间:2011-11-09 15:04:49

标签: javascript jquery ajax sjax

作为我正在研究的Javascript项目的一部分,有一些同步的ajax调用(我想这使它成为“sjax”,但我离题了)。我现在正在编写一个调试面板,它允许我通过包装$.ajax来测试一些人为模拟的网络条件。简单的事情:伪造500响应等,并使ajax调用需要更长的时间。

对于异步调用,它很简单。当真实响应返回时,添加setTimeout以使其在触发回调之前等待人工响应时间。但是,这显然不适用于同步调用,因为setTimeout不是同步的。

那么,有没有办法让Javascript程序在一段时间内执行阻塞等待?

我唯一能想到的就是这样:

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

有更好的解决方案吗?

(另外,请假设有阻止ajax调用的充分理由...... :-\

3 个答案:

答案 0 :(得分:5)

不要在JavaScript级别上执行此操作。获取Fiddler等代理,并设置AutoResponder以延迟一段时间的通话。

答案 1 :(得分:2)

如果只是出于调试目的而产生人为延迟:

alert('block me one more time');

在ECMAscript中没有合理的其他方法来阻止代码。由于Javascript是在浏览器用于渲染DOM和某些其他东西的同一个线程(“UI线程”)中执行的,因此整个节目的设计不会阻止任何内容。

当然你可以通过使用循环伪造它,但它是对节目的歪曲。

答案 2 :(得分:0)

我认为这段代码可能会有所帮助

// 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()

并测试......

// // // 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 // // //