Cách sử dụng setTimeout() và setInterval() trong JavaScript – https://final-blade.com

Đôi khi có một số hành chúng chúng ta không muốn thực hiện ngay lập tức, mà muốn chúng sẽ được thực hiện ở một khoảng thời gian nhất định. Ví dụ sau 10 giây kể từ khi người dùng truy cập trang web chẳng hạn. Để làm được điều này thì JavaScript có hàm hỗ trợ chúng ta làm điều đó. Trong bài viết này tôi sẽ giới thiệu về setTimeout() setInterval() trong JavaScript. Hãy cùng nhau tìm hiểu nhé.

  • setTimeout cho phép chúng ta chạy một function một lần sau khoảng thời gian nhất định.
  • setInterval cho phép chúng ta chạy một function lặp đi lặp lại, bắt đầu sau một khoảng thời gian, sau đó lặp lại liên tục trong khoảng thời gian đó.

Các phương pháp này không phải là một phần của đặc tả JavaScript. Nhưng hầu hết những môi trường tự nhiên đều có bộ lên lịch nội bộ và phân phối những hàm này. Đặc biệt, chúng được tương hỗ trên tổng thể những trình duyệt và Node. js .

Hàm setTimeout trong JavaScript

Cú pháp:

1

lettimerId=setTimeout(func|code,[delay],[arg1],[arg2],…)

Trong đó:

func|code

Một function hoặc một chuỗi code để thực thi. Thông thường, đó là một function. Vì nguyên do lịch sử vẻ vang, một chuỗi code cũng hoàn toàn có thể được truyền vào, nhưng điều đó không được khuyến nghị .

delay

Độ trễ trước khi chạy, tính bằng mili giây ( 1000 ms = 1 giây ), theo mặc định là 0 .

arg1arg2

Đối số cho hàm ( không được tương hỗ trong IE9 – )

Ví dụ: đoạn code này gọi function sayHi () sau một giây:

12345

functionsayHi(){

alert(‘ Hello ‘);

}

setTimeout(sayHi,1000);

Với những đối số :

12345

functionsayHi(phrase,who){

alert(phrase+’, ‘+who);

}

setTimeout(sayHi,1000,” Hello “,” John “);/ / Hello, John

Nếu đối số tiên phong là một chuỗi, thì JavaScript sẽ tạo một hàm từ nó. Vì vậy, điều này cũng sẽ hoạt động giải trí :

1

setTimeout(” alert ( ‘ Hello ‘ ) “,1000);

Nhưng sử dụng chuỗi không được khuyến khích, hãy sử dụng những hàm mũi tên thay vì sử dụng chuỗi, như sau :

1

setTimeout(()=>alert(‘ Hello ‘),1000);

Xem thêm: Các loại function trong JavaScript.

Lưu ý

Các bạn mới làm quen đôi khi mắc lỗi khi thêm dấu ngoặc () sau hàm:

12

/ / sai !

setTimeout(sayHi(),1000);

Điều đó không hoạt động, vì setTimeout mong đợi một tham chiếu đến một hàm. Và ở đây sayHi() chạy hàm và kết quả thực thi của nó được chuyển đến setTimeout. Trong trường hợp này, kết quả của sayHi() là không xác định (hàm không trả về gì), vì vậy không có gì được lên lịch.

Hủy lên lịch với clearTimeout

Lệnh gọi setTimeout trả về timerId “định danh” mà chúng ta có thể sử dụng để hủy thực thi. Cú pháp hủy:

12

lettimerId=setTimeout(…);

clearTimeout(timerId);

Trong đoạn mã dưới đây, tôi lập lịch cho tính năng và sau đó hủy bỏ nó. Kết quả là không có gì xảy ra :

12345

lettimerId=setTimeout(()=>alert(” never happens “),1000);

alert(timerId);/ / định danh timerId

clearTimeout(timerId);

alert(timerId);

Như chúng ta có thể thấy từ đầu ra của hàm alert(), trong trình duyệt, mã định danh là một số. Trong các môi trường khác, đây có thể là một cái gì đó khác. Ví dụ, Node.js trả về một đối tượng bộ đếm thời gian với các phương thức bổ sung.

Hàm setInterval trong JavaScript

Phương thức setInterval có cùng cú pháp như setTimeout:

1

lettimerId=setInterval(func|code,[delay],[arg1],[arg2],…)

Tất cả các đối số đều có cùng ý nghĩa. Nhưng không giống như setTimeout, nó chạy chức năng không chỉ một lần mà lặp đi lặp lại sau một khoảng thời gian nhất định. Đây cũng là điểm khác nhau giữa setTimeout() và setInterval() trong JavaScript.

Để dừng các cuộc gọi tiếp theo, chúng ta nên sử dụng hàm clearInterval (timerId).

Ví dụ sau sẽ hiển thị thông tin sau mỗi 2 giây. Sau 5 giây, đầu ra bị dừng :

12345

/ / Hiển thị thông tin 2 giây một lần

lettimerId=setInterval(()=>alert(‘ tick ‘),2000);

/ / Sau 5 giây thì dừng

setTimeout(()=>{clearInterval(timerId);alert(‘ stop ‘);},5000);

Thời gian tiếp tục trong khi cảnh báo được hiển thị

Trong hầu hết các trình duyệt, bao gồm cả Chrome và Firefox, bộ đếm thời gian bên trong sẽ tiếp tục trong khi hiển thị alert/confirm/prompt.

Vì vậy, nếu bạn chạy mã ở trên và không vô hiệu hành lang cửa số cảnh báo nhắc nhở trong một thời hạn, thì cảnh báo nhắc nhở tiếp theo sẽ được hiển thị ngay lập tức khi bạn triển khai. Khoảng thời hạn trong thực tiễn giữa những cảnh báo nhắc nhở sẽ ngắn hơn 2 giây .

Hàm setTimeout lồng nhau

Có hai cách để thực hiện một cái gì đó lặp đi lặp lại trong một khoảng thời gian. Một là sử dụng hàm setInterval(), hai là sử dụng hàm setTimeout() lồng nhau. Giống như sau:

12345678

/ * * Thay vì sử dụng setInterval ( ) :

let timerId = setInterval ( ( ) => alert ( ‘ tick ‘ ), 2000 ) ;

* /

/ / Ta hoàn toàn có thể sử dụng setTimeout ( ) lồng nhau

lettimerId=

setTimeout

(functiontick(){

alert(‘ tick ‘);

timerId=setTimeout(tick,2000);/ / Được gọi sau khi kết thúc cuộc gọi hiện tại

},2000);

Hàm setTimeout ở trên lên lịch cho cuộc gọi tiếp theo ngay khi kết thúc cuộc gọi hiện tại .

Giữa setTimeout() và setInterval() trong JavaScript, thì hàm setTimout() sử dụng linh hoạt hơn setInterval(). Bởi vì cuộc gọi tiếp theo trong setTimeout có thể được lên lịch tùy thuộc vào kết quả của cuộc gọi hiện tại.

Ví dụ: chúng ta cần viết một dịch vụ gửi yêu cầu đến máy chủ cứ sau 5 giây yêu cầu dữ liệu, nhưng trong trường hợp máy chủ quá tải, nó nên tăng khoảng thời gian lên 10, 20, 40 giây…

12345678910111213

letdelay=5000;

lettimerId=setTimeout(functionrequest(){

…sendrequest…

if(yêucầukhôngthànhcôngdoquátảimáychủ){

/ / tăng interval cho lần chạy tiếp theo

delay *=2;

}

timerId=setTimeout(request,delay);

},delay);

Và nếu những tính năng mà tất cả chúng ta đang lên lịch sử dụng CPU, thì tất cả chúng ta hoàn toàn có thể đo thời hạn triển khai và lên kế hoạch cho cuộc gọi tiếp theo sớm hay muộn .

setTimeout lồng nhau cho phép đặt độ trễ giữa các lần thực thi chính xác hơn setInterval.

Hãy so sánh hai đoạn mã sau. Cái đầu tiên sử dụng setInterval:

1234

leti=1;

setInterval(function(){

func(i+ +);

},100);

Cái thứ hai sử dụng setTimeout lồng nhau:

12345

leti=1;

setTimeout(functionrun(){

func(i+ +);

setTimeout(run,100);

},100);

Đối với setInterval, bộ lập lịch nội bộ sẽ chạy func (i ++) sau mỗi 100ms:

sử dụng setInterval() trong JavaScript
Bạn có chú ý không ?

Độ trễ thực sự giữa các cuộc gọi func() cho setInterval ít hơn trong mã!

Điều đó là bình thường, vì thời gian thực thi của hàm func() “tiêu tốn” một phần của khoảng thời gian. Có thể quá trình thực thi của hàm func() hóa ra lâu hơn chúng ta mong đợi và mất hơn 100 mili giây.

Trong trường hợp này, nó sẽ đợi hàm func() hoàn thành, sau đó kiểm tra bộ lập lịch và nếu hết thời gian, nó sẽ chạy lại ngay lập tức.

Và đây là hình ảnh cho setTimeout lồng nhau:

Sử dụng setTimeout trong JavaScript

setTimeout lồng nhau sẽ đảm bảo độ trễ cố định (ở đây là 100ms). Đó là vì một cuộc gọi mới được lên kế hoạch vào cuối cuộc gọi trước đó.

Điều gì sẽ xảy ra khi ta set độ trễ của setTimeout là 0?

Có một trường hợp sử dụng đặc biệt: setTimeout (func, 0) hoặc chỉ setTimeout (func).

Bộ lập lịch sẽ gọi hàm func() càng sớm càng tốt. Nhưng bộ lập lịch sẽ chỉ gọi nó sau khi tập lệnh hiện đang thực thi hoàn tất.

Vì vậy, hàm được lên lịch sẽ chạy “ ngay sau ” tập lệnh hiện tại .
Ví dụ : hiệu quả đầu ra là “ Hello ”, sau đó là “ World ” :

123

setTimeout(()=>alert(” World “));

alert(” Hello “);

Dòng đầu tiên “đưa cuộc gọi vào lịch sau 0ms”. Nhưng trình lập lịch sẽ chỉ “kiểm tra lịch” sau khi tập lệnh hiện tại hoàn tất, vì vậy “Hello” là đầu tiên và “World” – sau nó.

Trong trình duyệt, có một số lượng giới hạn về tần suất những bộ hẹn giờ lồng nhau hoàn toàn có thể chạy. Tiêu chuẩn HTML5 standard cho biết : “ sau năm bộ hẹn giờ lồng nhau, khoảng chừng thời hạn buộc phải tối thiểu 4 mili giây. ” .
Hãy chứng tỏ ý nghĩa của nó với ví dụ bên dưới. Lệnh gọi setTimeout trong nó tự lên lịch lại với độ trễ bằng không. Mỗi cuộc gọi ghi nhớ thời hạn thực từ cuộc gọi trước đó trong mảng thời hạn. Sự chậm trễ thực sự trông như thế nào ? Hãy xem ví dụ sau :

123456789101112

letstart=Date.now();

lettimes=[];

setTimeout(functionrun(){

times.push(Date.now()-start);/ / nhớ độ trễ từ cuộc gọi trước

if(start+100

elsesetTimeout(run);/ / lên lịch lại

});

/ / Kết quả

/ / 1,1,1,1,9,15,20,24,30,35,40,45,50,55,59,64,70,75,80,85,90,95,100

Đầu tiên các cuộc gọi được gọi ngay lập tức, nhưng sau đó chúng ta có thể thấy 9, 15, 20, 24… Độ trễ bắt buộc trên 4 ms giữa các lần gọi có hiệu lực.

Điều tương tự cũng xảy ra nếu chúng ta sử dụng setInterval thay vì setTimeout: setInterval (f) chạy vài lần với độ trễ bằng 0 và sau đó với độ trễ trên 4 ms.

Đối với JavaScript phía sever, hạn chế đó không sống sót và sống sót những cách khác để lập lịch việc làm không đồng nhất ngay lập tức, như setImmediate cho Node. js. Vì vậy, quan tâm này dành riêng cho từng trình duyệt .

Kết luận

Cùng ôn lại một số kiến thức chính về hàm setTimeout() và setInterval() trong JavaScript đã học trong bài viết này nhé:

  • Phương thức setTimeout(func, delay, ...args) và setInterval(func, delay, ...args) cho phép chúng ta chạy function func() một hoặc lặp đi lặp lại sau delay milliseconds.
  • Để hủy thực thi, chúng ta nên gọi clearTimeout / clearInterval với giá trị được trả về bởi setTimeout / setInterval.
  • Lệnh gọi setTimeout lồng nhau là một giải pháp thay thế linh hoạt hơn cho setInterval, cho phép chúng tôi đặt thời gian giữa các lần thực hiện chính xác hơn.
  • Lập lịch với độ trễ bằng không với setTimeout (func, 0) (hoặc setTimeout (func)) được sử dụng để lập lịch cuộc gọi “càng sớm càng tốt, nhưng sau khi tập lệnh hiện tại hoàn tất”.
  • Trình duyệt giới hạn độ trễ tối thiểu cho năm cuộc gọi lồng nhau trở lên của setTimeout hoặc setInterval (sau cuộc gọi thứ 5) là 4ms.

Hãy chú ý quan tâm rằng toàn bộ những phương pháp lên lịch trình không bảo vệ độ trễ đúng chuẩn .