我有这个功能,它会ping我的服务器以进行特定的数据更改:
function connected() {
$.ajax({
success : function(d) {
if (d.success) {
// return data
} else {
setTimeout(connected, 200);
}
}
});
}
(显然,代码已被剥离到最低限度,以使我的意图更清晰)
我想要做的是在找到bool时返回true,所以我可以去
if (connected()) {
// process data
}
(显然数据存储在全局变量中。)
有没有办法实现这个目标?
修改
我可以创建一个'暂停'功能:
function pauseScript(ms) {
ms += new Date().getTime();
while (new Date().getTime() < ms) {}
}
然后更改我的代码以排除setTimeout()(并包含其他一些东西)
function connected() {
var value;
$.ajax({
async: false,
success : function(d) {
if (d.success) {
// set data
value = true;
} else {
pauseScript(200);
value = connected();
}
}
});
return value;
}
然而这感觉有点hacky!
答案 0 :(得分:2)
为此,最佳应该在异步模式下继续:
function connected(callback) {
$.ajax({
success : function(d) {
if (d.success) {
callback();
} else {
setTimeout(function() {
connected(callback);
}, 200);
}
}
});
}
//Using :
connected(function(){
//Here i finish my scan result
});
也许,我不太确定在这种情况下,你需要绑定它(我的意思是绑定范围): http://www.robertsosinski.com/2009/04/28/binding-scope-in-javascript/
答案 1 :(得分:1)
如果您定位的浏览器支持JavaScript 1.7或更高版本(在撰写本文时,我认为只有Gecko浏览器可以),那么您可以利用生成器来执行此操作。让我们首先让你的connect
函数异步(并且更容易进行测试):
function connectAsync(callback) {
// Pretend we always succeed after a second.
// You could use some other asynchronous code instead.
setTimeout(callback, 1000, true);
}
现在将您的调用代码包装到一个函数中。 (它必须是一个函数。)
function main() {
console.log("Connecting...");
if(!(yield connect())) {
console.log("Failed to connect.");
yield; return;
}
console.log("Connected.");
yield;
}
注意所有yield
到处都是。这是魔术的一部分。当我们在每个函数退出点之前调用yield
和connect
时,我们需要yield
。
现在我们需要定义connect
。你可能想要同步一堆异步函数,所以让我们创建一个使函数同步的函数。
function synchronize(async) {
return function synchronous() {
return {func: async, args: arguments};
};
}
然后我们可以用connect
创建connectAsync
:
var connect = synchronize(connectAsync);
现在我们需要创建一个运行所有这些魔法的函数。这是:
function run(sync) {
var args = Array.prototype.slice.call(arguments);
var runCallback = args.length ? args[args.length - 1] : null;
if(args.length) {
args.splice(args.length - 1, 1);
}
var generator = sync.apply(window, args);
runInternal(generator.next());
function runInternal(value) {
if(typeof value === 'undefined') {
if(runCallback) {
return runCallback();
}else{
return;
}
}
function callback(result) {
return runInternal(generator.send(result));
}
var args = Array.prototype.slice.call(value.args);
args.push(callback);
value.func.apply(window, args);
}
}
现在,您可以使用此魔法运行main
函数:
run(main);
我应该注意main
不再可以返回值。 run
可以采用第二个参数:在同步函数完成时调用的回调。要将参数传递给main
(例如1
,2
和3
),您可以这样称呼:
run(main, 1, 2, 3, callback);
如果您不想收回回复,请传递null
或undefined
。
要尝试此操作,您必须将type
标记的script
设置为text/javascript; version=1.7
。 JavaScript 1.7添加了新的关键字(如yield
),因此它是向后兼容的,因此必须有一些方法可以将自己与旧代码区分开来。
有关生成器的更多信息,请参阅this page on MDN。有关协同程序的更多信息,请参阅the article on Wikipedia。
由于JavaScript 1.7的支持有限,所有这些都说不实用。此外,看到这种代码并不常见,因此可能难以理解和维护。 我建议只使用异步样式,如Deisss's answer中所示。然而,它是可能这样做很好。