Nội dung bài viết
Video học lập trình mỗi ngày
Settimer js để sử dụng setTimeout hay setInterval thì quá đơn giản, nhưng để hiểu cơ chế hoạt động của setTimeout và setInterval là một điều không hề dễ dàng, cho nên trường hợp dưới đây là một sai lầm do không hiểu hoạt động của hai cơ chế trên.
Chú ý: Bài viết dành cho lập trình viên ở tầm trung và cao. Những dev mới không cần đọc quá kỹ, tránh tình trạng hiểu bậy bạ.
jquery settimer Cơ chế hoạt động
settimer javascript là một cơ chế hoạt động của setTimeout và setInterval là di chuyển function() được chỉ định ra khỏi quá trình thực thi này và đợi cho đến vòng tiếp theo của Vòng lặp sự kiện, sau đó kiểm tra xem thời gian được chỉ định đã hết chưa.
Nếu nó đến, hãy thực thi mã tương ứng; nếu không, hãy đợi đến vòng tiếp theo của Vòng lặp sự kiện để đánh giá lại. Ở đây, không giải thích hiều về setTimeout và setInterval. Và bài viết này cũng áp dụng cho việc học "jquery settimer".
settimer js
Một câu hỏi nâng cao
for (var i = 0; i < 4; i++) { setTimeout(function () { console.log(i); }, 1000); }
Nhìn vào, dev mới thì sẽ nói rằng output sẽ là 0,1,2,3. Nhưng chúng ta không hề nhìn thấy vậy. mà nó sẽ xuất ra 4,4,4,4. Vì sao? Chúng ta bàn luận một chút về vấn đề này. Vòng lặp for là một tác vụ đồng bộ. Tại sao nó xuất ra như vậy?
Trả lời: Bởi vì setTimeout() chèn vào hàng đợi , ngay cả khi thời gian thực hiện được thay đổi từ 1000 thành 0, kết quả đó vẫn được xuất. Vậy vấn đề này đã nảy sinh và được giải quyết như thế nào?
Hãy đọc tiếp dưới đây đề xuất những phương án khắc phục lỗi trên
Closure vs setTimeout
for (let i = 0; i < 4; i++) { (function (j) { setTimeout(function () { console.log(j); }, 1000 * i) })(i); }
Sau khi thực thi, một giá trị sẽ được xuất sau mỗi 1 giây, đó là: 0 1 2 3 Phương thức này khéo léo sử dụng IIFE các biểu thức hàm được khai báo để thực thi để giải quyết các vấn đề do Closure() gây ra. Thay đổi var thành let, sử dụng cú pháp ES6
Promise vs setTimeout
const tasks = []; const output = (i) => new Promise((resolve) => { setTimeout(() => { console.log(i); resolve(); }, 1000 * i); }); // Tạo tất cả Promise for (var i = 0; i < 5; i++) { tasks.push(output(i)); } // Promise.all(tasks).then(() => { setTimeout(() => { console.log(i); }, 1000) })
Sau khi thực thi, một giá trị sẽ được xuất sau mỗi 1 giây, đó là:0 1 2 3 4 5
Ưu điểm: Cải thiện khả năng của code
Lưu ý: Nên tìm hiểu thêm về Promise reject, chớ không là rơi vào tình trang treo.
async await vs setTimeout
Cách sử dụng async await trong ES7 có khả năng tốt hơn. Và mình thích điều đó.
const sleep = (timeountMS) => new Promise((resolve) => { setTimeout(resolve, timeountMS); }); (async () => { for (var i = 0; i < 5; i++) { await sleep(1000); console.log(i); } await sleep(1000); console.log(i); })();
Sau khi thực thi, một giá trị sẽ được xuất sau mỗi 1 giây, đó là: 0 1 2 3 4 5
Chốt lại bài viết
Điểm kiến thức tổng hợp:
- Hiểu khái niệm về luồng đơn JS: làm một việc trong một khoảng thời gian
- Hiểu hàng đợi tác vụ: tác vụ đồng bộ, tác vụ không đồng bộ
- Hiểu vòng lặp sự kiện
- Hiểu câu lệnh nào sẽ được đặt trong hàng đợi tác vụ không đồng bộ
- Hiểu khi nào câu lệnh được đặt trong hàng đợi tác vụ không đồng bộ