Selbst wenn Sie alles vergessen, was Sie über JavaScript wissen, werden Sie nie vergessen: Es blockiert.
Stellen Sie sich vor, dass in Ihrem Browser ein magischer Elf lebt, der für den normalen Betrieb des Browsers verantwortlich ist. Ob es darum geht, HTML zu rendern, auf Menübefehle zu reagieren, den Bildschirm zu rendern, Mausklicks zu verarbeiten oder JavaScript-Funktionen auszuführen, alles wird von einem einzigen Elf erledigt. Es ist so beschäftigt, dass es jeweils nur eine Sache bewältigen kann. Wenn Sie ihm eine Reihe von Aufgaben gleichzeitig geben, erstellt er eine lange To-Do-Liste und erledigt diese der Reihe nach.
Menschen möchten oft, dass das JavaScript, das Komponenten und Event-Handler initialisiert, so schnell wie möglich ausgeführt wird. Einige weniger wichtige Hintergrundaufgaben wirken sich jedoch nicht direkt auf die Benutzererfahrung aus, wie zum Beispiel:
Statistiken aufzeichnen
Senden Sie Daten an ein soziales Netzwerk (oder fügen Sie die Schaltfläche „Teilen“ hinzu)
Vorinstallierte Inhalte
HTML vorverarbeiten oder vorrendern
Sie sind zeitlich nicht streng, aber damit die Seite reaktionsfähig bleibt, werden sie erst ausgeführt, wenn der Benutzer auf der Seite scrollt oder mit dem Inhalt interagiert.
Eine Option sind Web Worker, die Code gleichzeitig in unabhängigen Threads ausführen können. Ideal zum Vorladen und Vorverarbeiten, aber Sie haben keinen direkten Zugriff auf das DOM oder können es nicht aktualisieren. Sie können dies in Ihrem eigenen Code umgehen, es gibt jedoch keine Garantie dafür, dass Skripte von Drittanbietern wie Google Analytics dies niemals benötigen.
Eine weitere Option ist setTimeout, beispielsweise setTimeout(doSomething, 1);. Sobald andere unmittelbare Aufgaben ausgeführt wurden, führt der Browser die Funktion doSomething() aus. Tatsächlich wurde es ans Ende der To-Do-Liste verschoben. Leider wird die Funktion unabhängig vom Verarbeitungsbedarf aufgerufen.
#requestIdleCallback
requestIdleCallback ist eine neue API, mit der weniger wichtige geplante Hintergrundaufgaben ausgeführt werden, wenn der Browser eine Pause einlegt. Es erinnert unweigerlich an requestAnimationFrame, das die Funktion ausführt, die Animation vor dem nächsten Neuzeichnen zu aktualisieren. Wenn Sie mehr wissen möchten, klicken Sie hier: Verwenden Sie requestAnimationFrame, um einfache Animationen zu erstellen.
RequestIdleCallback-Funktionsüberwachung:
if ('requestIdleCallback' in window) { // requestIdleCallback supported requestIdleCallback(backgroundTask); } else { // no support - do something else setTimeout(backgroundTask1, 1); setTimeout(backgroundTask2, 1); setTimeout(backgroundTask3, 1); }
Sie können auch Konfigurationsparameterobjekte angeben, z. B. Timeout,
requestIdleCallback(backgroundTask, { timeout: 3000; });
Stellen Sie sicher, dass die Funktion innerhalb von 3 Sekunden aufgerufen wird, unabhängig davon, ob der Browser inaktiv ist.
Wenn das Deadline-Objekt die folgenden Parameter übergibt, führt requestIdleCallback den Rückruf nur einmal aus:
didTimeout – Wird auf „true“ gesetzt, wenn ein optionales Timeout ausgelöst wird
timeRemaining() – Funktion gibt die Anzahl der Millisekunden zurück, die zur Ausführung der Aufgabe verbleiben
timeRemaining() reserviert bis zu 50 ms für die Aufgabenausführung. Wenn dieser Grenzwert überschritten wird, wird die Aufgabe nicht gestoppt. Es ist jedoch am besten, requestIdleCallback erneut aufzurufen, um die weitere Verarbeitung zu veranlassen.
Lassen Sie uns ein einfaches Beispiel erstellen, um mehrere Aufgaben nacheinander auszuführen. Die Funktionsreferenz der Aufgabe wird im Array gespeichert:
//待执行的函数数组 var task = [ background1, background2, background3 ]; if ('requestIdleCallback' in window) { //支持 requestIdleCallback requestIdleCallback(backgroundTask); } else { //不支持 —— 立刻执行所有任务 while (task.length) { setTimeout(task.shift(), 1); } } //requestIdleCallback 回调函数 function backgroundTask(deadline) { //如果存在,执行下一个任务 while (deadline.timeRemaining() > 0 && task.length > 0) { task.shift()(); } //需要的话,安排进一步任务 if (task.length > 0) { requestIdleCallback(backgroundTask); } }
#Was sollte zwischen requestIdleCallback nicht getan werden?
Paul Lewis erwähnte in seinem Artikel, dass die von einem requestIdleCallback ausgeführten Aufgaben in kleine Stücke geschnitten werden sollten. Es ist nicht für unvorhersehbare Zeitsituationen geeignet (z. B. für den Betrieb von DOM, es ist besser, den Rückruf von requestAnimationFrame zu verwenden). Seien Sie auch vorsichtig, wenn Sie Versprechen auflösen (oder ablehnen). Die Rückruffunktion wird sofort nach Abschluss des inaktiven Rückrufs ausgeführt, auch wenn keine Zeit mehr übrig ist.
#requestIdleCallback Browser-Unterstützung
requestIdleCallback ist eine experimentelle Funktion, die Spezifikation ist immer noch instabil und es ist nicht überraschend, dass API-Änderungen auftreten. Chrome 47 wird unterstützt...sollte vor Ende 2015 verfügbar sein. Opera sollte diesem Beispiel folgen. Sowohl Microsoft als auch Mozilla überlegen, ob APIs Promises unterstützen sollten. Apple ist wie üblich pessimistisch.
Paul Lewis (oben erwähnt) hat einen einfachen requestIdleCallback-Shim geschrieben, der das Leerlaufüberwachungsverhalten des Browsers simulieren kann, aber kein Polyfill ist (der Unterschied zwischen Shim und Polyfill).
requestIdleCallback-Shim-Code lautet wie folgt:
/*! * Copyright Google Inc. All rights reserved. * * Licensed under the Apache License, Version . (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-. * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. */ /* * @see https://developers.google.com/web/updates///using-requestidlecallback */ window.requestIdleCallback = window.requestIdleCallback || function (cb) { var start = Date.now(); return setTimeout(function () { cb({ didTimeout: false, timeRemaining: function () { return Math.max(, - (Date.now() - start)); } }); }, ); } window.cancelIdleCallback = window.cancelIdleCallback || function (id) { clearTimeout(id); }
ps: So führen Sie eine geplante Aufgabe aus
1. Führen Sie GPEDIT.MSC aus
2. Computerkonfiguration auswählen
--- Windows-Einstellungen
Sicherheitseinstellungen
—Lokale Strategie
—-Zuweisung von Benutzerrechten
Doppelklicken Sie rechts auf „Auf diesen Computer über das Netzwerk zugreifen“
Fügen Sie die erforderlichen Benutzernamen zur Liste hinzu.
3. --- Sicherheitseinstellungen
---Sichere Wahl
Aktivieren Sie „Serverbetreibern erlauben, Aufgaben zu planen“
4.-----Lokale Strategie
--- Als Batch-Job anmelden
Fügen Sie die erforderlichen Benutzernamen zur Liste hinzu.
5.-----Lokale Strategie
--- Erlauben Sie Computern und Benutzern, für die Delegierung vertrauenswürdig zu sein
Fügen Sie die erforderlichen Benutzernamen zur Liste hinzu.
Am besten ist es, der Administrator-Benutzer zu sein.
Wenn der Aufgabenplan nicht gestartet werden kann, Eingabeaufforderungscode: 0X80041315
Lösung: Es gibt zwei Möglichkeiten: Der Dienst „Task Scheduler“ im System ist nicht gestartet. Sie können während des Betriebs „services.msc“ eingeben, um zu überprüfen, ob der Dienst „Task Scheduler“ auf „Bereits“ eingestellt ist „Deaktivieren“, wenn ja, doppelklicken Sie einfach darauf, um den Starttyp auf „Automatisch“ zu ändern und eine geplante Aufgabe zurückzusetzen, um sie auszuführen.
Wenn Ihr aktuelles Konto auf automatische Anmeldung eingestellt ist und das Anmeldekennwort leer ist, kann dies auch dazu führen, dass der Aufgabenplan nicht rechtzeitig ausgeführt wird. In der XP Professional Edition müssen Sie „gpedit.msc“ ausführen Bearbeiten Sie die Gruppenrichtlinie: Erweitern Sie „Computer“-Konfiguration→Windows-Einstellungen→Sicherheitseinstellungen→Lokale Computerrichtlinie→Sicherheitsoptionen“, doppelklicken Sie rechts auf das Element „Konten: Lokale Konten mit leeren Passwörtern erlauben nur Konsolenanmeldung“ und wählen Sie „ „Deaktiviert“ im Popup-Dialogfeld.