使用 setTimeout 和递归来查看某些内容是否"ready"?



我正试图找出一个好方法来检查某个异步调用是否"就绪"。我有一个运行$.ajax的函数,在回调函数中将全局范围中的布尔变量设置为true(以及其他一些东西)。在ajax调用之前,该布尔变量为false。

我想要另一个检索"其他东西"的函数。由于ajax调用是异步的,显然我不能立即检索它,因为它可能还不存在。这就是这个布尔变量的作用。我想我可以每隔100毫秒检查一次这个布尔值是否为真,当它为真时,然后去检索并返回"其他东西"。

代码方面,它看起来像这样:

window.FOO = window.FOO || {};
;(function() {
var isReady = false;
var stuff;
$.ajax({
...
success: function(data) {
stuff = data;
isReady = true;
}
})
FOO.getStuff = function() {
// How to check if it's "ready"?
};
}
... (somewhere else)...
var stuff = FOO.getStuff();

我为FOO.getStuff尝试了以下操作,但没有成功,因为(我认为)setTimeout是异步的:

FOO.getStuff = function() {
if (isReady) {
return stuff;
}
var theStuff;
setTimeout(function() {
theStuff = FOO.getStuff();
}, 100);
return theStuff;
};

使用控制台,我可以看到它做了正确的事情。。。但是第一个CCD_ 2调用在后续调用之前返回

有更好的方法吗?

编辑:为了澄清,我希望ajax调用保持异步。我完全同意getStuff()调用是同步的,因为ajax调用会非常快,而且在大多数情况下,getStuff)会在稍后调用(在used做了一些事情之后)。

根据您的评论,我有您的答案。为了解决异步问题,我们应该执行异步操作。

var stuff;
var stuffQueue = [];
$.ajax({
success: function(data) {
stuff = data;
if( stuffQueue.length > 0 ){
for(var i in stuffQueue){
var callback = stuffQueue[i];
callback(stuff);
}
stuffQueue = [];
} 
}
});
function getStuff(callback){
//stuff has been loaded?
if( stuff ){
callback(stuff);
}else{
stuffQueue.push(callback);
}
}

获取东西调用:

var something = getStuff(function(stuff){
console.log(stuff);
});

这应该可以解决您的用例。让我告诉你更多信息,我有一个JavaScript模板引擎,还不是开源的,但我一直在专业项目中使用,我只用一个HTTP请求加载所有模板,我使该请求异步:false,因为它是项目的依赖项。

有人说async false是邪恶的,我不这么认为,邪恶的是用错了它。加载模板文件主文件是async:false可以工作的一个很好的例子。

另外,我建议您阅读有关承诺的内容:http://www.html5rocks.com/en/tutorials/es6/promises/

与Danie Aranda的想法相似,我想建议您使用自定义事件。

var isReady = true;
$.ajax({
beforeSend: function() {
isReady = false;
},
success: function(data) {
isReady = true;
$(document).trigger('display-stuff', data);
}
});
Foo.getStuff = function(data) {
if (!isReady) {
$(document).one('display-stuff', Foo.getStuff);
return;
}
// do something
};

最新更新