在 while 循环中延迟
Deferred in a while loop
所以我想在 jquery 中执行延迟的 ajax 请求,直到我收到特定的服务器响应(非空)。我该怎么做?
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
});
});
}
你不能在 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();
如果你想让整个事情成为return一个承诺,你可以这样做:
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。尽可能快地不断轮询某些服务器几乎从来都不是正确的事情。如果您只有几个用户,这可能会很好地工作,但是一旦您有很多用户,所有要做的就是用空轮询请求淹没您的服务器,而在大多数情况下,没有什么可以 return客户端。这是处理负载的噩梦。最好找一个不轮询的架构,但如果你要轮询,那么至少使用某种定时器在未来某个时间轮询而不是尽可能快。
P.P.S。如果你真的只是在等待服务器上的一些值发生变化,那么也许你应该使用 webSocket 连接。这样,客户端就建立了与服务器的连接并且连接持续存在,然后在将来的任何时候,服务器都可以简单地向客户端发送消息。客户端根本不需要轮询。这可以大大提高您的服务器基础架构的效率,并可以提供更及时的结果。
要给予更大的控制权,写doUntilResult()
接受:
- 一个
doThis
回调函数,它确定要做什么,以及re-try/terminate条件。
- 一个整数,决定调用之间的延迟。
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()
函数,可以改变您对 "done until" 的想法而无需重新编写。一切都在调用(或调用)中指定。
原题调用如下:
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 链终止于 returns null
每当轮询要继续的函数中。
Here's a simple demo 生成一个0-10的随机数; 9 或更大的数字被视为数据;低于 9 将导致重试。 (在控制台中监控进度)。
所以我想在 jquery 中执行延迟的 ajax 请求,直到我收到特定的服务器响应(非空)。我该怎么做?
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
});
});
}
你不能在 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();
如果你想让整个事情成为return一个承诺,你可以这样做:
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。尽可能快地不断轮询某些服务器几乎从来都不是正确的事情。如果您只有几个用户,这可能会很好地工作,但是一旦您有很多用户,所有要做的就是用空轮询请求淹没您的服务器,而在大多数情况下,没有什么可以 return客户端。这是处理负载的噩梦。最好找一个不轮询的架构,但如果你要轮询,那么至少使用某种定时器在未来某个时间轮询而不是尽可能快。
P.P.S。如果你真的只是在等待服务器上的一些值发生变化,那么也许你应该使用 webSocket 连接。这样,客户端就建立了与服务器的连接并且连接持续存在,然后在将来的任何时候,服务器都可以简单地向客户端发送消息。客户端根本不需要轮询。这可以大大提高您的服务器基础架构的效率,并可以提供更及时的结果。
要给予更大的控制权,写doUntilResult()
接受:
- 一个
doThis
回调函数,它确定要做什么,以及re-try/terminate条件。 - 一个整数,决定调用之间的延迟。
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()
函数,可以改变您对 "done until" 的想法而无需重新编写。一切都在调用(或调用)中指定。
原题调用如下:
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 链终止于 returns null
每当轮询要继续的函数中。
Here's a simple demo 生成一个0-10的随机数; 9 或更大的数字被视为数据;低于 9 将导致重试。 (在控制台中监控进度)。