Câu trả lời:
Đơn giản nhất là chỉ cần gọi hàm trực tiếp lần đầu tiên:
foo();
setInterval(foo, delay);
Tuy nhiên, có những lý do chính đáng để tránh setInterval
- đặc biệt trong một số trường hợp, toàn bộ các setInterval
sự kiện có thể đến ngay sau đó mà không có bất kỳ sự chậm trễ nào. Một lý do khác là nếu bạn muốn dừng vòng lặp, bạn phải gọi một cách rõ ràng clearInterval
, điều đó có nghĩa là bạn phải nhớ tay cầm được trả về từ setInterval
cuộc gọi ban đầu .
Vì vậy, một phương pháp thay thế là foo
tự kích hoạt các cuộc gọi tiếp theo bằng cách sử dụng setTimeout
:
function foo() {
// do stuff
// ...
// and schedule a repeat
setTimeout(foo, delay);
}
// start the cycle
foo();
Điều này đảm bảo rằng có ít nhất một khoảng delay
giữa các cuộc gọi. Nó cũng giúp việc hủy vòng lặp dễ dàng hơn nếu được yêu cầu - bạn chỉ không gọi setTimeout
khi đạt đến điều kiện chấm dứt vòng lặp.
Tốt hơn nữa, bạn có thể gói tất cả trong một biểu thức hàm được gọi ngay lập tức để tạo ra hàm, sau đó tự gọi lại như trên và tự động bắt đầu vòng lặp:
(function foo() {
...
setTimeout(foo, delay);
})();
trong đó xác định hàm và bắt đầu chu trình tất cả trong một lần.
setTimeout
?
setInterval
sự kiện có thể đến ngay lập tức với nhau mà không có bất kỳ sự chậm trễ nào.
setTimeout
phương thức?
Tôi không chắc là tôi có hiểu đúng về bạn không, nhưng bạn có thể dễ dàng làm điều gì đó như thế này:
setInterval(function hello() {
console.log('world');
return hello;
}(), 5000);
Rõ ràng có nhiều cách để làm điều này, nhưng đó là cách ngắn gọn nhất mà tôi có thể nghĩ ra.
arguments.callee
không khả dụng trong chế độ nghiêm ngặt ES5
Tôi vấp phải câu hỏi này do cùng một vấn đề nhưng không có câu trả lời nào có ích nếu bạn cần cư xử chính xác như thế setInterval()
nhưng với sự khác biệt duy nhất là hàm được gọi ngay từ đầu.
Đây là giải pháp của tôi cho vấn đề này:
function setIntervalImmediately(func, interval) {
func();
return setInterval(func, interval);
}
Ưu điểm của giải pháp này:
setInterval
có có thể dễ dàng được điều chỉnh bằng cách thay thếclearInterval()
sauThí dụ:
// create 1 second interval with immediate execution
var myInterval = setIntervalImmediately( _ => {
console.log('hello');
}, 1000);
// clear interval after 4.5 seconds
setTimeout( _ => {
clearInterval(myInterval);
}, 4500);
Để táo tợn, nếu bạn thực sự cần sử dụng setInterval
thì bạn cũng có thể thay thế bản gốc setInterval
. Do đó, không cần thay đổi mã khi thêm mã này trước mã hiện tại của bạn:
var setIntervalOrig = setInterval;
setInterval = function(func, interval) {
func();
return setIntervalOrig(func, interval);
}
Tuy nhiên, tất cả các lợi thế như được liệt kê ở trên áp dụng ở đây nhưng không cần thay thế.
setTimeout
giải pháp vì nó trả về một setInterval
đối tượng. Để tránh gọi các hàm có thể nằm sau mã và do đó không được xác định tại thời điểm hiện tại, tôi gói lệnh gọi hàm đầu tiên trong một setTimeout
hàm như thế này: setTimeout(function(){ func();},0);
Hàm đầu tiên sau đó được gọi sau chu trình xử lý hiện tại, cũng ngay lập tức , nhưng là nhiều lỗi đã được chứng minh.
Bạn có thể gói setInterval()
trong một hàm cung cấp hành vi đó:
function instantGratification( fn, delay ) {
fn();
setInterval( fn, delay );
}
... Sau đó sử dụng nó như thế này:
instantGratification( function() {
console.log( 'invoked' );
}, 3000);
Đây là một trình bao bọc để làm đẹp nó nếu bạn cần nó:
(function() {
var originalSetInterval = window.setInterval;
window.setInterval = function(fn, delay, runImmediately) {
if(runImmediately) fn();
return originalSetInterval(fn, delay);
};
})();
Đặt đối số thứ ba của setInterval thành true và nó sẽ chạy lần đầu tiên ngay sau khi gọi setInterval:
setInterval(function() { console.log("hello world"); }, 5000, true);
Hoặc bỏ qua đối số thứ ba và nó sẽ giữ lại hành vi ban đầu của nó:
setInterval(function() { console.log("hello world"); }, 5000);
Một số trình duyệt hỗ trợ các đối số bổ sung cho setInterval mà trình bao bọc này không tính đến; Tôi nghĩ rằng chúng hiếm khi được sử dụng, nhưng hãy ghi nhớ nếu bạn cần chúng.
Đối với ai đó cần phải mang bên ngoài this
bên trong như thể đó là một chức năng mũi tên.
(function f() {
this.emit("...");
setTimeout(f.bind(this), 1000);
}).bind(this)();
Nếu việc sản xuất rác ở trên làm phiền bạn, bạn có thể đóng cửa thay thế.
(that => {
(function f() {
that.emit("...");
setTimeout(f, 1000);
})();
})(this);
Hoặc có thể xem xét sử dụng các @autobind
trang trí tùy thuộc vào mã của bạn.
Tôi sẽ đề nghị gọi các hàm theo trình tự sau
var _timer = setInterval(foo, delay, params);
foo(params)
Bạn cũng có thể chuyển _timer
cho foo, nếu bạn muốn với clearInterval(_timer)
một điều kiện nhất định
var _timer = setInterval(function() { foo(_timer, params) }, delay);
foo(_timer, params);
Đây là một phiên bản đơn giản cho người mới mà không có sự lộn xộn xung quanh. Nó chỉ khai báo hàm, gọi nó, sau đó bắt đầu khoảng. Đó là nó.
//Declare your function here
function My_Function(){
console.log("foo");
}
//Call the function first
My_Function();
//Set the interval
var interval = window.setInterval( My_Function, 500 );
Có một gói npm tiện lợi được gọi là FirstInterval (công bố đầy đủ, nó là của tôi).
Nhiều ví dụ ở đây không bao gồm xử lý tham số và thay đổi hành vi mặc định của setInterval
bất kỳ dự án lớn nào là xấu. Từ các tài liệu:
Mẫu này
setInterval(callback, 1000, p1, p2);
callback(p1, p2);
giống hệt với
firstInterval(callback, 1000, p1, p2);
Nếu bạn là trường học cũ trong trình duyệt và không muốn phụ thuộc, thì đó là cách dễ dàng cắt và dán từ mã.
// YCombinator
function anonymous(fnc) {
return function() {
fnc.apply(fnc, arguments);
return fnc;
}
}
// Invoking the first time:
setInterval(anonymous(function() {
console.log("bar");
})(), 4000);
// Not invoking the first time:
setInterval(anonymous(function() {
console.log("foo");
}), 4000);
// Or simple:
setInterval(function() {
console.log("baz");
}, 4000);
Ok điều này rất phức tạp, vì vậy, hãy để tôi nói đơn giản hơn:
function hello(status ) {
console.log('world', ++status.count);
return status;
}
setInterval(hello, 5 * 1000, hello({ count: 0 }));
Bạn có thể đặt thời gian trễ ban đầu rất nhỏ (ví dụ 100) và đặt thời gian trễ mong muốn trong hàm:
var delay = 100;
function foo() {
console.log("Change initial delay-time to what you want.");
delay = 12000;
setTimeout(foo, delay);
}
Có vấn đề với cuộc gọi không đồng bộ ngay lập tức của chức năng của bạn, bởi vì setTimeout / setInterval tiêu chuẩn có thời gian chờ tối thiểu khoảng vài mili giây ngay cả khi bạn trực tiếp đặt nó thành 0. Nó gây ra bởi một công việc cụ thể của trình duyệt.
Một ví dụ về mã với độ trễ bằng không THỰC SỰ hoạt động trong Chrome, Safari, Opera
function setZeroTimeout(callback) {
var channel = new MessageChannel();
channel.port1.onmessage = callback;
channel.port2.postMessage('');
}
Bạn có thể tìm thêm thông tin ở đây
Và sau cuộc gọi thủ công đầu tiên, bạn có thể tạo một khoảng với chức năng của mình.
thực sự nhanh nhất là làm
interval = setInterval(myFunction(),45000)
cái này sẽ gọi chức năng của tôi, và sau đó sẽ thực hiện nó sau mỗi 45 giây, khác với làm
interval = setInterval(myfunction, 45000)
mà sẽ không gọi nó, nhưng chỉ lên lịch
myFunction()
không trở lại chính nó. Thay vào đó, sửa đổi từng chức năng được gọi bởi setInterval
nó là một cách tiếp cận tốt hơn để bọc setInterval
một lần giống như các câu trả lời khác đang đề xuất.
function
một lần và sau đó thực hiệnsetInterval()