2011-09-26 69 views
6

我有一個類,ChatRoom,它只能在接收到長時間運行的HTTP請求(可能需要1秒或30秒)後才能呈現。所以我需要延遲渲染,直到ChatRoom.json不爲空。異步延遲JS直到滿足條件

在下面的代碼中,我使用了Closure Library的goog.async.ConditionalDelay。它可以工作,但有沒有更好的方法(可能不需要Closure庫)來做到這一點?

ChatRoom.prototype.json = null; // received after a long-running HTTP request. 

ChatRoom.prototype.render = function() { 
    var thisChatRoom = this; 

    function onReady() { 
     console.log("Received JSON", thisChatRoom.json); 
     // Do rendering... 
    } 

    function onFailure() { 
     alert('Sorry, an error occurred. The chat room couldn\'t open'); 
    } 

    function isReady() { 
     if (thisChatRoom.json != null) { 
      return true; 
     } 
     console.log("Waiting for chat room JSON..."); 
     return false; 
    } 

    // If there is a JSON request in progress, wait until it completes. 
    if (isReady()) { 
     onReady(); 
    } else { 
     var delay = new goog.async.ConditionalDelay(isReady); 
     delay.onSuccess = onReady; 
     delay.onFailure = onFailure; 
     delay.start(500, 5000); 
    } 
} 

請注意,「while(json == null){}」是不可能的,因爲這將是同步的(阻止所有其他JS執行)。

+2

爲什麼不使用來自HTTP請求的回調? – SLaks

+0

我無法使用該回調,因爲可能會在返回JSON之前或在返回10分鐘之後調用render。基本上,我希望能夠隨時調用render()。 –

+1

您仍然可以使用回調。在'render'中,檢查JSON是否已經返回,如果沒有,則添加到一個回調數組中。或者只是使用jQuery的新Deferred對象,它爲你做到了這一點。 – SLaks

回答

20

考慮一下:

(function wait() { 
    if (chatroom.json) { 
     chatroom.render(); 
    } else { 
     setTimeout(wait, 500); 
    } 
})(); 

這將第二檢查每半。

現場演示:http://jsfiddle.net/kBgTx/

-1

我想出答案是這樣的:

var count = 0; 
// Number of functions that need to run. This can be dynamically generated 
// In this case I call check(data, cb) a total of 3 times 
var functionNum = 3; 
function toCallAfter(){ 
    console.log('I am a delayed function'); 
} 

我有這樣的,在一個循環規律和兩次跑了一次檢查功能:

check(data, function(err){ // check is my asynchronous function to check data integrity 
    if (err){ 
     return cb(null, { // cb() is the return function for the containing function 
      errCode: 'MISSINGINFO', 
      statusCode: 403, 
      message : 'All mandatory fields must be filled in' 
     }); 
    } // This part here is an implicit else 
    count++; // Increment count each time required functions complete to 
      // keep track of how many function have completed 
    if (count === functionNum) { 
     return anon(); 
    } 
    return; 
}); 
// Run twice more in a loop 
for(var i = 0; i < 2; i++) { 
    check(data, function(err) { // calls check again in a loop 
     if (err){ 
      return cb(null, { 
       errCode: 'MISSINGINFO', 
       statusCode: 403, 
       message : 'All mandatory fields must be filled in' 
      }); 
     } 
     count++; 
     if (count === functionNum) { 
      return toCallAfter(); 
     } 
     return; 
    }); 
} 

最後,我想指出一個重要的性能故障在替代(和非常常見的)答案ER:

(function wait() { 
    if (chatroom.json) { 
     chatroom.render(); 
    } else { 
     setTimeout(wait, 500); 
    } 
})(); 

在這種情況下,你基本上是抱着瀏覽器或服務器(如果使用的node.js)人質500毫秒,每檢查這是一個令人難以置信的很長一段時間的電腦。意味着巨大的性能打擊。直接跟蹤所需完成功能的解決方案不受時間限制,只要所有功能完成即可立即運行。

+0

500毫秒是有生命的,但是拿着JS線程的人質你不是。 JavaScript中的異步函數不是線程阻塞的,它們在未來的某個時刻排隊等待執行。 接受的答案很常見,因爲它是慣用的javascript,並且當您沒有可以響應的「準備就緒」事件時,您可以執行此操作。 –