【问题标题】:Asynchronously delay JS until a condition is met异步延迟 JS 直到满足条件
【发布时间】:2011-09-26 18:16:52
【问题描述】:

我有一个类 ChatRoom,它只能在它接收到一个长时间运行的 HTTP 请求(可能需要 1 秒或 30 秒)后才能呈现。所以我需要延迟渲染,直到ChatRoom.json 不为空。

在下面的代码中,我使用了闭包库的goog.async.ConditionalDelay。它可以工作,但是有没有更好的方法(可能不需要闭包库)来做到这一点?

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 执行)。

【问题讨论】:

  • 为什么不使用来自 HTTP 请求的回调?
  • 我无法使用该回调,因为可能会在 JSON 返回之前或在返回 10 分钟后调用 render。基本上,我希望能够在我想要的任何时间点调用 render()。
  • 您仍然可以使用回调。在 render 中,检查 JSON 是否已返回,如果没有,则添加到回调数组。或者只是使用 jQuery 的新 Deferred 对象,它会为你做这件事。

标签: javascript asynchronous google-closure-library


【解决方案1】:

考虑一下:

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

这将每半秒检查一次。

现场演示: http://jsfiddle.net/kBgTx/

【讨论】:

    【解决方案2】:

    你也可以使用 lodash 的 debouncer 来实现这一点。

    import _debounce from 'lodash/debounce';
    
    const wait = (() => {
        if ( chatroom.json ) {
            chatroom.render();
        } else {
          _debounce(wait, 500)();
        }
    })();

    【讨论】:

      【解决方案3】:

      我想出的答案是这样的:

      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;
          });
      }
      

      最后,我想指出替代(并且非常常见)答案中的一个重大性能错误:

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

      在这种情况下,对于每次检查,您实际上将浏览器或服务器(如果使用 node.js)作为人质 500 毫秒,这对于计算机来说是非常长的时间。意味着巨大的性能冲击。我的直接跟踪所需完成功能的解决方案不受时间限制,并且会在所有功能完成后立即运行。

      【讨论】:

      • 500 毫秒是一生是的,但你不是持有 JS 线程的人质。 javascript 中的异步函数不是线程阻塞的,它们会在将来的某个时间排队等待执行。公认的答案很常见,因为它是惯用的 javascript,并且当您没有可以响应的“就绪”事件时,它的性能可以达到最高水平。
      猜你喜欢
      • 1970-01-01
      • 2021-06-10
      • 1970-01-01
      • 1970-01-01
      • 2019-11-10
      • 2014-10-18
      • 2021-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多