在while循环中延迟

时间:2016-07-23 22:25:33

标签: jquery ajax asynchronous deferred

所以我想在jquery中做一个延迟的ajax请求,直到我收到一个特定的服务器响应(非null)。我该怎么做呢?

while (data.response != null) {
  $.ajax(..).done(function(data);
}

function doUntilResult() {
    Server.doA().done(function(data) {
      Server.doB(data).done(function(result) {
          //if result == null, repeat again
      });
    });
}

2 个答案:

答案 0 :(得分:2)

你不能在Javascript中这样循环。 Javascript是一个事件驱动的系统。当你像这样循环时,没有其他事件可以被处理。因此,即使您的第一个Ajax调用也不会被处理。实际上,当客户端试图同时进行数百万次ajax调用时,你可能会因耗尽一些资源而将JS引擎驱动到地面。

相反,您可以异步使用ajax结果,然后根据结果决定是否再次调用它:

function poll() {
    $.ajax(...).then(function(data) {
        if (!data.xxxx) {
            // call it again after some short delay
            setTimeout(poll, 1000);
        } else {
            // got the result we wanted, process it
        }
    })
}

// start the polling
poll();

如果你想让整件事都回复承诺,你可以这样做:

function delay(t) {
    return new $.Deferred(function(def) {
        setTimeout(def.resolve, t);
    }).promise();
}

function poll() {
    return $.ajax(...).then(function(data) {
        if (!data.xxxx) {
            // call it again after some short delay
            return delay(1000).then(poll);
        } else {
            // got the result we wanted, process it
            return someValue;
        }
    })
}

// start the polling
poll().then(function(result) {
    // process result here
});

P.S。尽可能快地不断地轮询某个服务器绝对不是正确的事情。如果您只有几个用户,这可能会正常工作,但只要您拥有大量用户,所有这一切都会使您的服务器无法在大多数情况下使用空轮询请求,而无法返回客户端。这是处理负载的噩梦。找到一个不轮询的架构会更好,但是如果要进行轮询,那么至少要使用某种计时器在未来的某个时间进行轮询,而不是尽可能快地进行轮询。

P.P.S。如果您真的只是等待服务器上的某些值更改,那么您可能应该使用webSocket连接。这样,客户端建立与服务器的连接并且连接仍然存在,然后在将来的任何时候,服务器都可以简单地向客户端发送消息。客户端根本不需要轮询。这可以在您的服务器基础架构上大大提高效率,并可以提供更及时的结果。

答案 1 :(得分:0)

为了给予大量控制,请写doUntilResult()接受:

  • 一个doThis回调函数,用于确定要执行的操作以及重试/终止条件。
  • 一个整数,用于确定呼叫之间的延迟。
function doUntilResult(doThis, t) {
    function delay() {
        return $.Deferred(function(dfrd) {
            window.setTimeout(dfrd.resolve, t);
        });
    }
    function poll() {
        return $.when(doThis()).then(function(data) { // $.when() caters for non-async functions to be passed.
            return (data === null) ? delay().then(poll) : data; // continue on null, otherwise return data.
        });
    }
    return poll();
}

现在,你有一个通用的doUntilResult()功能,可以改变你的想法,直到"没有重写。在呼叫(或呼叫)中指定了所有内容。

对于原始问题,请致电如下:

doUntilResult(function() {
    return $.ajax(..).then(function(data) {
        return data || null; // adjust as required to ensure that `null` is returned only for the "continue" condition.
    });
}, 1000); // 1 second delay between calls

对于编辑过的问题,请致电如下:

doUntilResult(function() {
    return Server.doA().then(function(data) {
        return Server.doB(data);
    }).then(function(result) {
        return result || null; // adjust as required ...
    });
}, 1000); // 1 second delay between calls

无论您想做什么,始终确保回调的.then链终止于每当轮询继续时返回null的函数。

Here's a simple demo生成0-10的随机数; 9或更大的数字被视为数据; 9岁以下将重新尝试。 (监视控制台的进度)。