JavaScript set 超时循环返回值

JavaScript set timeout loop return value

本文关键字:返回值 循环 超时 set JavaScript      更新时间:2023-09-26

我有这个函数,它可以ping我的服务器以获取特定的数据更改:

function connected() {
  $.ajax({
    success : function(d) {
      if (d.success) {
        // return data
      } else {
        setTimeout(connected, 200);
      }
    }
  });
}

(显然代码已被剥离到最低限度,以使我的意图更清晰)

我想做的是在找到时返回一个布尔值 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;
}

然而,这感觉有点笨拙!

为此,最好继续在异步模式下:

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/

如果您的目标浏览器支持 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无处不在。这是魔法的一部分。当我们调用connect时,我们需要一个yield,在每个函数退出点之前需要一个yield

现在我们需要定义connect .你可能有一堆你可能想要同步的异步函数,所以让我们创建一个使函数同步的函数。

function synchronize(async) {
    return function synchronous() {
        return {func: async, args: arguments};
    };
}

然后我们可以用它从connectAsync创建connect

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(例如,123 ),您可以像这样调用它:

run(main, 1, 2, 3, callback);

如果您不想要回调,请传递nullundefined


要尝试此操作,您必须将script标记的type设置为 text/javascript; version=1.7 。JavaScript 1.7 添加了新的关键字(如 yield ),因此它是向后不兼容的,因此必须有某种方式将自己与旧代码区分开来。

有关生成器的更多信息,请参阅MDN上的此页面。有关协程的更多信息,请参阅维基百科上的文章。

综上所述,由于对 JavaScript 1.7 的支持有限,这是不切实际的。此外,看到这种代码并不常见,因此可能难以理解和维护。我建议只使用异步样式,如 Deisss 的答案所示。然而,这样做是可以做到的。