JavaScript 告诉 setInterval 只触发 x 次数?

有没有可能限制 setInterval 在 javascript 中触发的次数?

79849 次浏览

You can call clearInterval() after x calls:

var x = 0;
var intervalID = setInterval(function () {


// Your logic here


if (++x === 5) {
window.clearInterval(intervalID);
}
}, 1000);

To avoid global variables, an improvement of the above would be:

function setIntervalX(callback, delay, repetitions) {
var x = 0;
var intervalID = window.setInterval(function () {


callback();


if (++x === repetitions) {
window.clearInterval(intervalID);
}
}, delay);
}

Then you can call the new setInvervalX() function as follows:

// This will be repeated 5 times with 1 second intervals:
setIntervalX(function () {
// Your logic here
}, 1000, 5);

You can set a timeout that calls clearInterval. This should work:

function setTimedInterval(callback, delay, timeout){
var id=window.setInterval(callback, delay);
window.setTimeout(function(){
window.clearInterval(id);
}, timeout);
}

This will clear the interval after 10 calls

<html>
<body>


<input type="text" id="clock" />
<script language=javascript>
var numOfCalls = 0;
var int=self.setInterval("clock()",1000);
function clock()
{
var d=new Date();
var t=d.toLocaleTimeString();
document.getElementById("clock").value=t;
numOfCalls++;
if(numOfCalls == 10)
window.clearInterval(int);
}
</script>
</form>




</body>
</html>

I personally prefer to use setTimeout() spaced out to achieve the same effect

// Set a function to run every "interval" seconds a total of "x" times
var x = 10;
var interval = 1000;


for (var i = 0; i < x; i++) {
setTimeout(function () {
// Do Something
}, i * interval)
}

There's no clean up required with clearInterval()

You can enclose it to avoid variables leaking and it looks pretty clean :)

// Definition
function setIntervalLimited(callback, interval, x) {


for (var i = 0; i < x; i++) {
setTimeout(callback, i * interval);
}


}


// Usage
setIntervalLimited(function() {
console.log('hit');          // => hit...hit...etc (every second, stops after 10)
}, 1000, 10)

You can use setTimeout and a for loop.

var numberOfTimes = 20;
delay = 1000;


for (let i = 0; i < numberOfTimes; i++) {
setTimeout( doSomething, delay * i);
}

I made a small package that does this for NodeJS.

https://www.npmjs.com/package/count-interval

It's a drop-in replacement for setInterval (including parameter passing), but it takes an additional count parameter. This example prints a message once every second, but only 3 times.

const countInterval = require('./countInterval');


const timer = countInterval(() => {
console.log('fired!', new Date());
}, 1000, 3);

And for those of you preferring setTimeout and loving recursion here is my suggestion ;)

const setIntervalX = (fn, delay, times) => {
if(!times) return


setTimeout(() => {
fn()
setIntervalX(fn, delay, times-1)
}, delay)
}

Then as suggested you can call the new setInvervalX() function as follows:

// This will be repeated every for 5 times with 1 second intervals:
setIntervalX(function () {
// Your logic here
}, 1000, 5);

You can do this actually very simply with setTimeout() and an incremental counter.

var i = 0; // counter for the timer
function doSomething() {
console.log("1 second"); // your actual code here, alternatively call an other function here
if (++i < 10)
{   // only reset the timer when maximum of 10 times it is fired
console.log("reset the timer");
setTimeout(doSomething, 1000); // reset the timer
}
}
setTimeout(doSomething, 1000);  // init the first

This answer is based on SO: Repeating setTimeout and a nice, neat and tidy small combination with this.

You can use Six

SetIntervalX: Limit the number of times that setInterval will fire

import { setIntervalX } from "https://deno.land/x/six/mod.ts";
import { randomNumber } from "https://deno.land/x/random_number/mod.ts";


const API_URL = "https://leap.deno.dev";


async function checkAPIStatus() {
const startTime = performance.now();


const randomYear = randomNumber({ min: 2000, max: 10_000 });


const response = await fetch(`${API_URL}/${randomYear}`);


const data = await response.json();


console.log(`Is ${randomYear} a leap year? ${data.leapYear}.`);


const entTime = performance.now();


console.log(`Request took ${(entTime - startTime) / 1000} seconds.`);
}


setIntervalX(checkAPIStatus, 2000, 15);

Web Page: https://ulti.js.org/six

Repository: https://github.com/UltiRequiem/six

It includes documentation, 100% code coverage, and examples!

Works on Deno, Node.js and the browser!