2014-09-02 37 views
0

我覺得答案是在那裏,但我不知道要查找什麼。我查看了deferpromise,但我不知道如何應用,如果我希望它適用於自己。推遲功能,如果它已經在statechange上運行 - js

如果update_content()正在運行,我不希望在第一次完成之前再次調用它。你可以看到我的可怕的僞代碼,如果它已經在運行,我希望它等待運行update_content()。一旦完成,它會再次運行。從fadeIn/Outs等完成需要1-3秒,並且我希望每個statechange都等待,直到前一個請求完成。順便說一下,沒有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; 
    } 

} 
+0

您的問題的一般答案是,您掛鉤到其他操作完成時觸發的某種事件,以及觸發事件發生時,您將開始下一個操作。關於如何做到這一點的具體細節,我認爲你必須向我們展示'update_content()'代碼,以便我們知道如何知道它何時完成或何時運行。另外,你是否會處理每一個'statechange'事件(例如,如果'update_content()'仍在繼續,將它們保存在一個隊列中),還是隻需要處理最近的一個呢? – jfriend00 2014-09-02 21:25:13

+0

@ jfriend00我希望排隊他們,但我不知道該怎麼做。我不認爲'update_content()'代碼會起作用,儘管我覺得我可能需要返回一個完整的東西或其他內容 – 2014-09-02 21:43:23

+0

解決方案必須知道何時執行'update_content()'以及如何觸發下一個排隊的項目完成後。我們需要'udpate_content()'來爲解決方案的關鍵部分提供建議。假設它是一系列異步操作(如淡入淡出),它不像從中返回值那麼簡單,因爲異步操作將在函數本身完成後的某個時間後完成。我們需要查看該代碼以瞭解如何跟蹤何時完成。一旦我們知道如何知道update_content()完成時,隊列就不難了。 – jfriend00 2014-09-02 21:46:06

回答

2

首先,你需要的時候update_content()做就知道了。對於您可以使用您的兩個動畫一些承諾並返回時任何動畫在此功能啓動完成(這可能,如果沒有動畫開始立即解決)的是解決一個承諾:

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

+0

哇,令人驚歎,完美。它在第一次運行時完美運行,並排隊完成任務。你真了不起,而且是個好朋友! – 2014-09-03 12:46:56

相關問題