如果它已经在statechange-js上运行,则推迟函数

时间:2014-09-02 20:40:20

标签: javascript jquery-deferred history.js

我觉得答案就在那里,但我不知道该怎么查。我查看了deferpromise,但如果我希望将其应用于自身,我不确定如何应用它。

如果update_content()正在运行,我不希望在第一次完成之前再次调用它。

History.Adapter.bind(window, 'statechange', function() {

    var event_state = History.getState();

    // bad pseudo code
    if(update_content() is running, wait till it is finished(function() { 
         update_content(event_state.data.html); 
    }

});

正如您可以通过我可怕的伪代码看到的那样,我希望它等待运行update_content()(如果它已经运行)。一旦完成,它将再次运行。从fadeIn / Outs等完成需要1-3秒,我希望每个状态转换都等到上一个请求完成。

顺便说一下,没有AJAX。我希望它在这个意义上是同步的。

如何将功能延迟运行直至完成运行?

以下是update_content()代码:

// this function updates page content with ajax and cool effects!
function update_content(data) {
    if(data == null) return;

var id = $(data).prop('id'),
    content = "#" + id,
    header = 0;

    // if the header is full, header = 0.  if it's tiny, header = 1
    if($('#navbar.affix').length) { header = 1; }

    // if the page that needs to be loaded is NOT on the page
    // this could be #main, #content, etc
    if(!$(content).length) {
        $(data).hide().appendTo('#main_wrapper');       
    }

    // show the homepage $('#main')
    // fades the content viewer out. no positioning is done on the homepage.
    if(id == "main") {

        if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }

        $('#main').siblings(':visible').center(header); // puts visible content on TOP of page

        $('#main')// /.center(header)
            .show();  // home page goes behind content
        $('#main').siblings().fadeOut(600, function() { // fadeout content overlay, and ON COMPLETE
                $(this).hide(); // hide that shit               
            });
        if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }

        return;

}

    // show the content viewer $('#content')
    // fades content viewer in
    if(id = "content") {

        $('#content')
            .center(header) // place on top and center
            .fadeIn(function() { // fade in, and ON COMPLETE
                $('#main').hide(); // quickly remove siblings - DO NOT USE FADE
                $(this).uncenter(); // places it static so it is normal

                if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }
        }); 

        return;
    }

}

1 个答案:

答案 0 :(得分:2)

首先,您需要知道update_content()何时完成。为此你可以在你的两个动画上使用一些promises并返回一个在这个函数中启动任何动画时解决的promise(如果没有动画启动,可以立即解决):​​

// this function updates page content with ajax and cool effects!
// it returns a promise that is resolved when any animations started in this
// function are done
var updateRunning = 0;
function update_content(data) {
    if(data == null) [
        // return an already resolved promise
        return $().promise();
    }

    ++updateRunning;

    var id = $(data).prop('id'),
    content = "#" + id,
    header = 0, p1, p2;

    // if the header is full, header = 0.  if it's tiny, header = 1
    if($('#navbar.affix').length) { header = 1; }

    // if the page that needs to be loaded is NOT on the page
    // this could be #main, #content, etc
    if(!$(content).length) {
        $(data).hide().appendTo('#main_wrapper');       
    }

    // show the homepage $('#main')
    // fades the content viewer out. no positioning is done on the homepage.
    if(id == "main") {

        if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }

        $('#main').siblings(':visible').center(header); // puts visible content on TOP of page

        $('#main')// /.center(header)
            .show();  // home page goes behind content
        p1 = $('#main').siblings().fadeOut(600, function() { // fadeout content overlay, and ON COMPLETE
                $(this).hide(); // hide that shit               
            }).promise();
        if(header == 1) { $('body, html').scrollTop(55); } else { window.scrollTo(0,0); }


    } else {

        // show the content viewer $('#content')
        // fades content viewer in
        if(id == "content") {

            p2 = $('#content')
                .center(header) // place on top and center
                .fadeIn(function() { // fade in, and ON COMPLETE
                    $('#main').hide(); // quickly remove siblings - DO NOT USE FADE
                    $(this).uncenter(); // places it static so it is normal

                    if(header == 1) { 
                        $('body, html').scrollTop(55); 
                    } else { 
                        window.scrollTo(0,0); 
                    }
            }).promise(); 

    }
    // note that either p1, p2 or both might be undefined here, but
    // $.when() should still work for us
    return $.when(p1, p2).always(function() {
        --updateRunning;
    });
}

仅供参考,我还将if (id = "content")更改为if (id == "content"),因为我认为您所拥有的是编码错误。

然后,为update_content()而不是update_content创建一个队列和一个包装器,并且使用此包装器的想法是,只要update_content()完成,它就会处理下一个排队的项目。您可以通过维护标志来判断update_content()是否正在运行。

var queue = [];
function update_content_wrapper(data) {
    if (updateRunning !== 0) {
        // just queue the data if update already running
        queue.push(data);
    } else {
         update_content(data).always(function() {
             // if items in the queue, get the oldest one
             if (queue.length) {
                 update_content_wrapper(queue.shift());
             }
         });
    }
}

然后,您可以在statechange事件上调用包装器函数,它将为您完成所有脏工作:

History.Adapter.bind(window, 'statechange', function() {
    var event_state = History.getState();
    update_content_wrapper(event_state.data.html);
});

您致电update_content()的其他任何地方,都应将其切换为致电update_content_wrapper()