2011-09-26 17 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,并且当您没有可以响应的“准备就绪”事件时,您可以执行此操作。 –