繁体   English   中英

循环中的 setTimeout() 不会在每次调用之间等待 3 秒

[英]setTimeout() in a loop does not wait 3 seconds between each call

我正在尝试访问 API 以提取股票数据。 免费计划只允许我每分钟拨打 5 个电话。 我正在尝试使用本机 JS/jQuery 进行调用。 使用一些示例代码,我将说明我的问题(使用 3 秒间隔)。 我最初认为将setTimeout()放在打印到控制台的 for 循环中会打印,等待 3 秒,打印,等待 3 秒,重复...但它所做的是等待 3 秒,然后打印所有行立刻。 我现在明白了。 “锁定”程序的执行似乎是不好的做法,但我开始认为这就是这里需要做的事情?

$(function() {
    for (var i = 0; i < 5; i++) {
        doSetTimeout(i);
    }
});

function doSetTimeout(i) {
  setTimeout(function() { console.log(i); }, 3000);
}

我还尝试使用 while 循环和时间延迟“锁定”程序。 但是我的整个浏览器都死机了,并且响应时间比输入的时间长得多。

function pauseExecution(miliseconds) {
  var currentTime = new Date().getTime();
     while (currentTime + miliseconds >= new Date().getTime()) {
     }
}

正如其他人提到的, setTimeout是异步的。 发生的事情是您正在安排5任务在大约3000ms后完成。 您应该做的是在前一个任务完成之前不要将另一个任务排队。 这可以通过大约一百万种方式实现。

异步/等待

如果可以,请使用async/await 它最简单,代码量最少。

 const delay = (ms) => { return new Promise((resolve) => { setTimeout(() => resolve(), ms); }, ms); }; $(async function() { for (var i = 0; i < 5; i++) { await delay(3000); console.log(i); } });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

承诺

创建一个承诺链,其中每个任务都依赖于delay和一个unit of work如果您不进行转译等unit of work它将起到与async/await类似的目的。 你必须小心使用catch ect 来准备这个生产。

 const delay = (ms) => { return new Promise((resolve) => { setTimeout(() => resolve(), ms); }, ms); }; $(function() { let task = delay(3000); const work = (i) => console.log(i); for (var i = 0; i < 5; i++) { let j = i; // you need this because of closures. task = task .finally(() => { work(j); }) .then(() => delay(3000)); } });
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

队列

这可能是最复杂的解决方案。 您创建一个blocking queue 所有任务都可以随时排队,但队列只会在当前任务调用next后才会执行下一个任务。 这不是生产就绪的,只是作为一个例子。 同步操作和异常处理存在堆栈溢出问题。

 const queue = () => { const tasks = []; let running = false; const add = (task) => { tasks.push(task); run(); }; const run = () => { if (!running) { running = true; const step = () => { if (tasks.length > 0) { tasks.shift()(step); } else { console.log('done'); running = false; } }; step(); }; }; return { add, run }; }; const q = queue(); for (let i = 0; i < 5; i++) { q.add((next) => { const j = i; // again because of closure scoping. setTimeout(() => { console.log(j); next(); }, 3000); }); }

设置间隔

如果您不需要阻止以前的操作(ajax/fetch),您可以简单地使用setInterval 这只是每N ms 安排一个任务,而不管先前任务的状态如何。

 let i = 0; const interval = setInterval(() => { if (i === 5) { clearInterval(interval); } else { console.log(i++); } }, 3000);

哦,我已经做了类似的事情,你需要做的是运行并等待 func 结束。

看这个例子来理解。

 function doSomthing(){ console.log("Somthing is done"); Start(); } function Start(){ setTimeout(doSomthing, 3000); } Start();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM