等待从 javascript 函数返回,直到满足条件
Posted
技术标签:
【中文标题】等待从 javascript 函数返回,直到满足条件【英文标题】:Wait to return from a javascript function until condition met 【发布时间】:2012-01-10 07:02:06 【问题描述】:这是一个奇怪的问题。我有一个使用 Crockford 式公共/私有成员构建的客户端对象:
var client = function()
var that, remote_data, other_data;
// add public interface
that.doStuff = function()...
// wait for remote resources to load
remote_data = jsonRequest1();
other_data = jsonRequest2();
return that;
;
我遇到的问题是,我需要在返回新的“那个”对象(表示客户端就绪)之前加载一些远程 JSON 资源。数据是异步返回的(显然),我正在设置布尔变量来指示每个远程资源何时返回。
我想过做如下的事情:
return whenInitialized(function() return that; );
whenInitialized 函数返回两个布尔标志是否为真。我会将它与 setInterval 结合使用,但我确信这不会起作用。
非常感谢您的建议。
【问题讨论】:
【参考方案1】:为了在异步操作成功后运行代码,您需要一个延续。它可以只是您的代码在操作完成时调用的回调。
类似这样的:
var client = function(done) // done is the callback
var that, remote_data, other_data;
// add public interface
that.doStuff = function()...
// wait for remote resources to load
var done1 = false, done2 = false;
var complete1 = function() done1 = true; if (done2) done(); ;
var complete2 = function() done2 = true; if (done1) done(); ;
remote_data = jsonRequest1(complete1);
other_data = jsonRequest2(complete2);
return that;
;
但是这些控制标志真的很烦人,而且不能真正扩展。一个更好的声明方式是使用类似jQuery deferreds:
$.when(jsonRequest1(), jsonRequest2()).then(done);
【讨论】:
+1 用于 jQuery 延迟。我才刚刚开始掌握它们的窍门,它们会做出如此美妙的事情。 谢谢乔丹。我理解按照您的建议使用回调模式,在数据全部加载后调用“完成”回调。示例用法: var my_client = client(function() alert('done!'); );但是,在等待回调时, my_client 变量将可用,处于无效状态。你会如何调和这个?我想一种解决方案是更改客户端界面,因此不需要返回客户端。 @Chris Johnson:是的,您可以将该客户端提供给回调:done(that)
,并且不要从 client
函数返回任何内容。那么你的客户端代码就像:client(function(my_client) ... );
.【参考方案2】:
您可以执行一个循环(可以选择超时)来等待异步完成。警告,这将(按要求)阻止所有其他功能,如果花费时间过长,可能会导致浏览器冻结。但是,您确实应该找出一种异步方式来做您需要的事情,而不是像这样阻塞。
var syncRequest = function(options)
var is_finished = false;
var result;
var finished_callback = function(response)
is_finished = true;
result = response.result;
ajax_request(options, finished_callback);
// timeout in 30 seconds
var timeout = (new Date()).getTime() + 30000;
while ( !is_finished )
if ( (new Date()).getTime() >= timeout )
alert('Request timed out');
// do nothing, just block and wait for the request to finish
return result;
【讨论】:
我之前做过类似的实验,但我的浏览器总是冻结。由于大多数浏览器只在一个线程中执行 javascript,因此使用轮询不是一个好主意(因为 JavaScript 没有sleep()
或类似的东西)。
确实如此。这是一个糟糕的解决方案,但对于 OP 的要求来说是一个有效的解决方案。最好找出一种异步方式来做这件事,我相信如果你想得够多,所有问题都有一个异步解决方案。
如果您要使用阻塞解决方案,为什么不首先执行同步 ajax 请求?
OP 要求提供阻塞解决方案。如果您正在执行 JSONP,则无法执行同步请求。以上是关于等待从 javascript 函数返回,直到满足条件的主要内容,如果未能解决你的问题,请参考以下文章