Chrome: thời gian chờ / khoảng thời gian bị treo trong tab nền?


130

Tôi đã kiểm tra tính chính xác của setTimeoutviệc sử dụng thử nghiệm này . Bây giờ tôi nhận thấy rằng (như mong đợi) setTimeoutkhông chính xác lắm nhưng đối với hầu hết các thiết bị không chính xác đáng kể. Bây giờ nếu tôi chạy thử nghiệm trong Chrome và để nó chạy trong tab nền (vì vậy, chuyển sang tab khác và duyệt trên đó), quay lại kiểm tra và kiểm tra kết quả te (nếu thử nghiệm kết thúc) thì chúng đã thay đổi đáng kể. Có vẻ như thời gian chờ đã chạy chậm hơn rất nhiều. Đã thử nghiệm trong FF4 hoặc IE9, điều này đã không xảy ra.

Vì vậy, có vẻ như Chrome tạm ngưng hoặc ít nhất là làm chậm quá trình thực thi javascript trong tab không có trọng tâm. Không thể tìm thấy nhiều trên mạng về chủ đề này. Điều đó có nghĩa là chúng tôi không thể chạy các tác vụ nền, ví dụ như kiểm tra định kỳ trên máy chủ bằng các cuộc gọi XHR và setInterval(tôi nghi ngờ sẽ thấy hành vi tương tự setInterval, sẽ viết một bài kiểm tra nếu có thời gian với tôi).

Có ai gặp phải điều này? Sẽ có một cách giải quyết cho việc đình chỉ / chậm lại này? Bạn có thể gọi nó là một lỗi và tôi có nên nộp nó như vậy không?


Hấp dẫn! Bạn có thể biết Chrome đang tạm dừng và tiếp tục lại bộ đếm thời gian hay khởi động lại nó không, khi bạn truy cập lại tab? Hay là hành vi ngẫu nhiên? Nó có liên quan gì đến thực tế là Chrome chạy các tab trong các quy trình độc lập không?
ParseA

@gAMBOOKa: hãy xem câu trả lời của @ pimvdb. Nó có khả năng chậm lại tối đa một lần mỗi giây.
KooiInc

4 năm sau và vấn đề này vẫn tồn tại. Tôi có một setTimeOut cho div với a transition, vì vậy không phải tất cả các div đều chuyển đổi cùng một lúc, mà thực sự là 15ms sau mỗi lần, tạo ra một số hiệu ứng cuộn. Khi tôi đi đến một tab khác và quay lại sau một thời gian, tất cả các chuyển đổi div cùng một lúc và setTimeOuthoàn toàn bị bỏ qua. Đó không phải là một vấn đề lớn đối với dự án của tôi, nhưng nó là một bổ sung kỳ lạ và không mong muốn.
Rvervuurt

Đối với hoạt hình của chúng tôi được gọi là setTimeout theo trình tự, giải pháp cho chúng tôi chỉ là đảm bảo rằng chúng tôi nhớ tay cầm / ID của bộ hẹn giờ (nó được trả về từ setTimeout) và trước khi chúng tôi đặt hẹn giờ mới, trước tiên chúng tôi gọi ClearTimeout đã xử lý. Trong trường hợp của chúng tôi, điều này có nghĩa là khi bạn quay lại tab, có thể có một chút khắt khe ban đầu về mặt hoạt hình đang phát nhưng nó tự sắp xếp khá nhanh và hoạt hình thông thường sẽ tiếp tục. Chúng tôi đã nghĩ rằng đây là một vấn đề với mã ra ban đầu.
Hành động Dan

Câu trả lời:


88

Gần đây tôi đã hỏi về điều này và đó là hành vi của thiết kế. Khi một tab không hoạt động, chỉ tối đa một lần mỗi giây, chức năng được gọi. Đây là thay đổi mã .

Có lẽ điều này sẽ giúp: Làm cách nào tôi có thể khiến setInterval cũng hoạt động khi một tab không hoạt động trong Chrome?

TL; DR: sử dụng Công nhân web .


3
cảm ơn, tôi nên xem với 'tab không hoạt động'. Đôi khi không phải là một người nói tiếng Anh bản địa là một khuyết tật.
KooiInc

1
@Kooilnc: Không vấn đề gì :) Tôi cũng không phải là người nói tiếng Anh bản ngữ.
pimvdb

22

Có một giải pháp để sử dụng Web Worker, vì chúng chạy trong quy trình riêng biệt và không bị chậm lại

Tôi đã viết một tập lệnh nhỏ có thể được sử dụng mà không cần thay đổi mã của bạn - nó chỉ đơn giản ghi đè các hàm setTimeout, ClearTimeout, setInterval, clearInterval

Chỉ cần bao gồm nó trước tất cả mã của bạn

http://github.com/turuslan/HackTimer


7
Điều đó thật tuyệt vời và tất cả nhưng hãy lưu ý rằng: 1. Công nhân không có quyền truy cập vào DOM, 2. Công nhân chỉ được thực hiện nếu họ ở trên một tệp riêng. Đây không phải là sự thay thế thả xuống cho setTimeout trong nhiều trường hợp.
Madara's Ghost

1
Bạn đã đúng, nhưng một số trình duyệt hiện đại cho phép sử dụng công nhân mà không cần tệp riêng của họ bằng cách sử dụng Blobs ( html5rocks.com/en/tutorials/workers/basics/#toc-inlineworkers )
Ruslan Tushov

1
Ngay cả với điều đó, Web Worker vẫn thiếu rất nhiều chức năng (cụ thể là DOM) cho phép chúng là sự thay thế an toàn cho setTimeout và co.
Ma của Madara

Điều gì về mã phải chạy trong giao diện người dùng, ví dụ, các tác vụ xử lý đồ họa nặng mà chúng tôi muốn hoàn thành trong khi chúng tôi làm các công việc khác?
Michael

Chà, bạn có thể tạo Công nhân, nhân viên dịch vụ và sử dụng API canvas bằng cách sử dụng url dữ liệu. new Worker('data:text/javascript,(' + function myWorkerCode () { /*...*/ } + '()'). Đây cũng là một cách hay để kiểm tra xem bạn có hỗ trợ nhập biểu thức không:try { eval('import("data:text/javascript,void 0")') } catch (e) { /* no support! */ }
Fábio Santos

9

Phát một âm thanh ~ trống buộc trình duyệt phải duy trì hiệu suất - Tôi đã phát hiện ra nó sau khi đọc nhận xét này: Làm cách nào để JavaScript chạy ở tốc độ bình thường trong Chrome ngay cả khi tab không hoạt động?

Tôi cần hiệu suất không giới hạn theo yêu cầu cho một trò chơi trình duyệt sử dụng WebSockets, vì vậy tôi biết từ kinh nghiệm sử dụng WebSockets không đảm bảo hiệu suất không giới hạn, nhưng từ các thử nghiệm, chơi một tệp âm thanh dường như đảm bảo nó

Đây là 2 vòng âm thanh trống mà tôi đã tạo cho mục đích này, bạn có thể sử dụng chúng một cách tự do, thương mại: http://adventure.land/sound/loops/empty_loop_for_js_performance.ogg http://adventure.land/sound/loops/empty_loop_for_j

(Chúng bao gồm tiếng ồn -58db, -60db không hoạt động)

Tôi chơi chúng, theo yêu cầu của người dùng, với Howler.js: https://github.com/goldfire/howler.js

function performance_trick()
{
    if(sounds.empty) return sounds.empty.play();
    sounds.empty = new Howl({
        src: ['/sounds/loops/empty_loop_for_js_performance.ogg','/sounds/loops/empty_loop_for_js_performance.wav'],
        volume:0.5,
        autoplay: true, loop: true,
    });
}

Thật đáng buồn khi không có phương thức tích hợp sẵn để bật / tắt hiệu suất javascript đầy đủ theo mặc định, tuy nhiên, các công cụ khai thác tiền điện tử có thể chiếm quyền điều khiển tất cả các luồng máy tính của bạn bằng Web Worker mà không cần bất kỳ lời nhắc nào: |


Cảm ơn bạn, 58db rất dễ đeo tai nghe tho, nhưng tắt tiếng trang web giải quyết vấn đề đó
Kaan Soral

1

Tôi đã phát hành gói npm khoảng thời gian dành cho nhân viên, thiết lập triển khaiInterval và ClearInterval bằng cách sử dụng Web-Worker để theo kịp và chạy trên các tab không hoạt động cho Chrome, Firefox và IE.

Hầu hết các trình duyệt hiện đại (Chrome, Firefox và IE), các khoảng thời gian (bộ định thời cửa sổ) được kẹp để bắn không quá một lần mỗi giây trong các tab không hoạt động.

Bạn có thể tìm thêm thông tin về

https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setInterval

https://developer.mozilla.org/en-US/docs/Web/API/Web_WorkftimeAPI/Using_web_workers#Timeouts_and_inter đạn


0

Tôi đã cập nhật lõi jQuery của mình lên 1.9.1 và nó đã giải quyết sự khác biệt giữa các khoảng thời gian trong các tab không hoạt động. Tôi sẽ thử trước, sau đó xem xét các tùy chọn ghi đè mã khác.


bạn đã nâng cấp phiên bản nào? Tôi đã gặp một số vấn đề về thời gian chờ (thanh trượt thư viện) với phiên bản ~ 1.6
dmi3y

0

đây là giải pháp của tôi có được mili giây hiện tại và so sánh nó với mili giây mà hàm được tạo. trong khoảng thời gian, nó sẽ cập nhật mili giây khi chạy chức năng. bạn cũng có thể lấy khoảng thời gian / thời gian chờ bằng id.

<script>

var nowMillisTimeout = [];
var timeout = [];
var nowMillisInterval = [];
var interval = [];

function getCurrentMillis(){
    var d = new Date();
    var now = d.getHours()+""+d.getMinutes()+""+d.getSeconds()+""+d.getMilliseconds();
    return now;
}

function setAccurateTimeout(callbackfunction, millis, id=0){
    nowMillisTimeout[id] = getCurrentMillis();
    timeout[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisTimeout[id] + +millis)){callbackfunction.call(); clearInterval(timeout[id]);} }, 10);
}

function setAccurateInterval(callbackfunction, millis, id=0){
    nowMillisInterval[id] = getCurrentMillis();
    interval[id] = setInterval(function(){ var now = getCurrentMillis(); if(now >= (+nowMillisInterval[id] + +millis)){callbackfunction.call(); nowMillisInterval[id] = getCurrentMillis();} }, 10);
}

//usage
setAccurateTimeout(function(){ console.log('test timeout'); }, 1000, 1);

setAccurateInterval(function(){ console.log('test interval'); }, 1000, 1);

</script>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.