2011-09-14 39 views
19

Tôi đang sử dụng chức năng setInterval() để gọi một hàm cứ 20 giây một lần. Tuy nhiên, một điều tôi nhận thấy là nó lần đầu tiên setInterval() thực sự gọi chức năng là lúc 20 giây (và không khi setInterval() được gọi). Đây là giải pháp hiện tại của tôi:JavaScript: Cách lấy setInterval() để bắt đầu ngay bây giờ?

dothis(); 
var i = setInterval(dothis, 20000); 

Có cách nào để đạt được điều này mà không có mã trùng lặp này không?

Trả lời

29

Phương pháp của bạn là cách thức hoạt động bình thường.

Nếu đây đi lên hơn và hơn, bạn có thể làm một chức năng tiện ích đó sẽ thực hiện xử lý đầu tiên và sau đó thiết lập khoảng thời gian:

function setIntervalAndExecute(fn, t) { 
    fn(); 
    return(setInterval(fn, t)); 
} 

Sau đó, trong mã của bạn, bạn có thể chỉ làm điều này:

var i = setIntervalAndExecute(dothis, 20000); 
+0

Điều cần biết. Cảm ơn! – Andrew

2

Nếu chức năng dothis của bạn không có nhu cầu khác về giá trị trả lại, bạn có thể tự trả lại giá trị đó.

Điều này sẽ cho phép bạn gọi và truyền nó cùng một lúc. Nếu giá trị trả lại bị bỏ qua, nó sẽ vô hại.

function dothis() { 
    // your code 
    return dothis; 
} 

var i = setInterval(dothis(), 20000); 

Nếu không, bạn có thể mở rộng Function.prototype để đưa ra một invoke và trả lại chức năng cho tất cả các chức năng của bạn:

DEMO:http://jsfiddle.net/ZXeUz/

Function.prototype.invoke_assign = function() { 
    var func = this, 
     args = arguments; 
    func.call.apply(func, arguments); 
    return function() { func.call.apply(func, args); }; 
}; 

setInterval(dothis.invoke_assign('thisArg', 1, 2, 3), 20000); 

// thisArg 1 2 3 
// thisArg 1 2 3 
// thisArg 1 2 3 
// ... 

Điều này thực sự tăng cường điều một chút . Nó cho phép bạn vượt qua một tập các đối số. Đối số đầu tiên sẽ đặt giá trị this của hàm bạn đang gọi và phần còn lại của các đối số sẽ được chuyển thành các đối số thông thường.

Vì hàm được trả về được gói trong một hàm khác, bạn sẽ có hành vi giống hệt nhau giữa lời gọi ban đầu và khoảng thời gian.

10

Bạn có thể thực hiện một chức năng ẩn danh và gọi ngay lập tức, ngoại trừ bạn sử dụng hàm setTimeout thay vì setInterval.

(function doStuff() { 
    //Do Stuff Here 
    setTimeout(doStuff,20000); 
})(); 

Điều này sẽ thực hiện chức năng, sau đó gọi lại sau 20 giây.

Lưu ý rằng tùy thuộc vào hành vi bạn mong muốn hoặc trong một số trường hợp để thực hiện, có thể tốt hơn khi sử dụng setTimeout trên setInterval. Sự khác biệt chính là các cuộc gọi setInterval có chức năng bất cứ khi nào timeout đó hết, REGARDLESS nếu cuộc gọi cuối cùng đã kết thúc thực hiện hoặc nếu xảy ra lỗi. Sử dụng setTimeout là thời trang này đảm bảo rằng chức năng kết thúc thực hiện của nó trước khi bộ đếm thời gian reset. Rất nhiều sự cân bằng là khá rõ ràng, nhưng nó là một điều tốt để ghi nhớ khi bạn thiết kế ứng dụng của bạn.

EDIT Để đáp lại mối quan tâm của patrick dw về việc cần phải hủy thời gian chờ.Giải pháp tốt nhất là không sử dụng các chức năng ẩn danh, và chỉ cần gọi nó sau khi khai

var timeout; 
function doStuff() { 
    //doStuff 
    timeout = setTimeout(doStuff,20000); 
} 
doStuff() 

Có điều này cũng tương tự như những gì các OP đã cố gắng để tránh, nhưng nó không loại bỏ sự cần thiết phải gọi hàm và sau đó gọi Hàm setInterval, vì vậy bạn lưu một dòng mã. Bạn có thể dừng và bắt đầu chức năng bất cứ lúc nào bằng cách:

//Stop it 
clearTimeout(timeout); 

//Start it 
doStuff(); 
+0

plus: 'setTimeout' là thích hợp hơn vì nó sẽ không tiếp tục lặp lại nếu có lỗi. – Hemlock

+0

+1 Tôi nghĩ rằng đây là một giải pháp tốt nếu không có nhu cầu khác để gọi hàm bên ngoài. – user113716

+0

... mặc dù bạn đang mất một chút chức năng với câu trả lời hiện tại của mình. OP có kết quả trả về 'setInterval' được gán cho một biến, điều này có thể ngụ ý rằng khoảng thời gian sẽ bị hủy bỏ tại một số điểm. Để tái tạo hành vi, bạn cần phải thực hiện cuộc gọi đệ quy thông qua nhóm 'setTimeout' khi trạng thái của một lá cờ có thể được thiết lập để tạm dừng lời gọi. – user113716

Các vấn đề liên quan