So starten Sie schnell mit VUE3.0: Einstieg ins Lernen
Wenn mehrere Kontexte auf SharedArrayBuffer zugreifen und gleichzeitig Vorgänge am Puffer ausführen, kann es zu Ressourcenkonfliktproblemen kommen. Die Atomics-API ermöglicht mehreren Kontexten das sichere Lesen und Schreiben eines SharedArrayBuffer, indem sie erzwingt, dass jeweils nur eine Operation auf dem Puffer ausgeführt werden kann.
Die Natur atomarer Operationen schließt Optimierungen (z. B. Neuordnung von Anweisungen) aus, die das Betriebssystem oder die Computerhardware normalerweise automatisch durchführen würden. Atomic-Operationen machen es auch unmöglich, gleichzeitig auf den Speicher zuzugreifen. Bei unsachgemäßer Verwendung kann es zu einer Verlangsamung der Programmausführung kommen. Aus diesem Grund besteht die ursprüngliche Entwurfsabsicht der Atomics-API darin, komplexe Multithread-JavaScript-Programme zu erstellen, die auf minimalem, aber stabilem basieren Atomares Verhalten.
Atomics API bietet eine Reihe einfacher Methoden zur Durchführung direkter Änderungsoperationen. In der ECMA-Spezifikation sind diese Methoden als AtomicReadModifyWrite-Operationen definiert. Unter der Haube lesen diese Methoden einen Wert von einer Stelle im SharedArrayBuffer, führen arithmetische und bitweise Operationen aus und schreiben das Ergebnis schließlich an dieselbe Stelle. Die atomare Natur dieser Vorgänge bedeutet, dass die oben beschriebenen Lese-, Änderungs- und Rückschreibvorgänge der Reihe nach ausgeführt werden und nicht durch andere Threads unterbrochen werden.
//Erstelle einen Puffer der Größe 1 let sharedArrayBuffer = new SharedArrayBuffer(1); //Unit8Arraylet basierend auf Puffer erstellen typedArray = new Unit8Array(sharedArrayBuffer); //Alle ArrayBuffers werden auf 0console.log(typedArray) initialisiert; //Unit8Array[0] //Führen Sie eine atomare Addition von 10 zum Wert am Index 0 durchAtomics.add(typedArray,0,10); //Unit8Array[10] //Führen Sie eine atomare Subtraktion von 10 für den Wert am Index 0 durchAtomics.sub(typedArray,0,10); //Unit8Array[0]
Der JavaScript-Compiler des Browsers und die CPU-Architektur selbst haben die Befugnis, Anweisungen neu anzuordnen, um die Effizienz der Programmausführung zu verbessern. Unter normalen Umständen kann die Single-Thread-Umgebung von JavaScript diese Optimierung jederzeit durchführen, aber die Neuanordnung von Anweisungen in Multi-Threads kann zu Ressourcenkonflikten führen und ist äußerst schwierig zu beheben.
Die Atomics-API löst dieses Problem im Wesentlichen auf zwei Arten:
Die Reihenfolge aller atomaren Anweisungen relativ zueinander wird nie neu angeordnet.
Durch die Verwendung atomarer Lese- oder Schreibvorgänge wird gewährleistet, dass nicht alle Anweisungen relativ zu atomaren Lese- und Schreibvorgängen neu angeordnet werden.
Neben dem Lesen und Schreiben von Pufferwerten können Atomics.load() und Atomics.store() auch „Code-Zäune“ aufbauen. Die JavaScript-Engine stellt sicher, dass nicht-atomare Anweisungen lokal relativ zu Load() und Store() neu angeordnet werden können, diese Neuanordnung verletzt jedoch nicht die Grenzen atomarer Lese- und Schreibvorgänge.
const sharedArrayBuffer = new SharedArrayBuffer(4); const view = new Unit32Array(sharedArrayBuffer); //Nicht-atomares Schreiben ausführen view[0] = 1; // Es kann garantiert werden, dass das nicht-atomare Schreiben vor diesem Lesevorgang abgeschlossen ist, daher wird 1console.log(Atomics.load(view,0)); hier definitiv gelesen. //1 //Atomisches Schreiben durchführen Atomics.store(view,0,2); // Nicht-atomares Lesen kann garantiert erfolgen, nachdem das atomare Schreiben abgeschlossen ist, und 2console.log(view[0]); wird hier definitiv gelesen. //2
Um ein kontinuierliches und unterbrechungsfreies Lesen zuerst und dann Schreiben sicherzustellen, stellt die Atomics API zwei Methoden bereit: Exchange() und CompareExchange(). Atomics.exchange() führt einen einfachen Austausch durch, der garantiert, dass andere Threads den Austausch nicht unterbrechen.
const sharedArrayBuffer = new SharedArrayBuffer(4); const view = new Unit32Array(sharedArrayBuffer); //Schreibe 10Atomics.store(view,0,10) bei Index 0; //Wert von Index 0 lesen und 5 in Index 0 schreibenconsole.log(Atomics.exchange(view,0,5)); //10 //Wert aus Index 0 lesen console.log(Atomics.load(view,0)); //5
In einem Multithread-Programm möchte ein Thread möglicherweise nur dann in einen gemeinsam genutzten Puffer schreiben, wenn seit dem letzten Lesen kein anderer Thread den Wert geändert hat. Wenn der Wert nicht geändert wurde, kann dieser Thread den aktualisierten Wert sicher schreiben: Wenn der Wert geändert wurde, wird durch die Ausführung eines Schreibvorgangs der von anderen Threads berechnete Wert zerstört. Für diese Art von Aufgabe stellt die Atomics API die Methode „compare-Exchange()“ bereit. Diese Methode führt den Schreibvorgang nur aus, wenn der Wert am Zielindex mit dem erwarteten Wert übereinstimmt.
Ohne einen Sperrmechanismus können Multithread-Programme komplexe Anforderungen nicht unterstützen. Zu diesem Zweck stellt die Atomics API Methoden bereit, die Linux Futex (schneller User-Space-Mutex) nachahmen. Obwohl diese Methoden an sich sehr einfach sind, können sie als Grundkomponenten für komplexere Schließmechanismen dienen.
Alle atomaren Futex-Operationen können nur in Int32Array-Ansichten und darüber hinaus nur innerhalb von Arbeitsthreads verwendet werden.
Cross-Document Messaging, manchmal auch XDM (Cross-Document Messaging) genannt, ist die Fähigkeit, Informationen zwischen verschiedenen Ausführungskontexten (z. B. verschiedenen Arbeitsthreads oder Seiten aus verschiedenen Quellen) zu übertragen.
Die Kodierungs-API wird hauptsächlich zum Konvertieren zwischen Zeichenfolgen und stereotypen Arrays verwendet.
Die Datei-API basiert weiterhin auf dem Dateieingabefeld im Formular, bietet jedoch die Möglichkeit, direkt auf Dateiinformationen zuzugreifen. HTML5 fügt dem DOM eine Dateisammlung für Dateieingabeelemente hinzu. Wenn der Benutzer eine oder mehrere Dateien im Dateifeld auswählt, enthält die Dateisammlung eine Reihe von Dateiobjekten, die die ausgewählten Dateien darstellen. Jedes Dateiobjekt verfügt über einige schreibgeschützte Attribute.
Der FileReader-Typ stellt einen asynchronen Dateilesemechanismus dar. Sie können sich FileReader ähnlich wie XMLHttpRequest vorstellen, mit der Ausnahme, dass er zum Lesen von Dateien aus dem Dateisystem anstelle von Daten vom Server verwendet wird. Der FileReader-Typ bietet mehrere Methoden zum Lesen von Dateidaten.
readAsText(file,encoding);//Nur-Text-Inhalt aus der Datei lesen und im Ergebnisattribut speichern
readAsDataURL(file);//Datei lesen und den Daten-URI des Inhalts im Ergebnisattribut speichern
readAsBinaryString(file); //Lesen Sie die Datei und speichern Sie die Binärdaten jedes Zeichens im Ergebnisattribut
readAsArrayBuffer(file); //Lesen Sie die Datei und speichern Sie den Dateiinhalt im Ergebnisattribut in Form von ArrayBuffer
Eine synchrone Version von FileReader-Typ.
In einigen Fällen müssen Sie möglicherweise einen Teil der Datei anstelle der gesamten Datei lesen. Zu diesem Zweck stellt das File-Objekt eine Methode namens „slice()“ bereit. Die Methode „slice()“ empfängt zwei Parameter: das Startbyte und die Anzahl der Bytes im Yaodu-Bereich. Diese Methode gibt eine Instanz von Blob zurück, die eigentlich eine Oberklasse von File ist.
Blob stellt ein binäres großes Objekt dar, das der Kapselungstyp von JavaScript für nicht veränderbare Binärdaten ist. Arrays, die Zeichenfolgen, ArrayBuffers, ArrayBufferViews und sogar andere Blobs enthalten, können zum Erstellen von Blobs verwendet werden. Der Blob-Konstruktor kann einen Optionsparameter empfangen und darin den MIME-Typ angeben.
Streams API wurde entwickelt, um ein einfaches, aber grundlegendes Problem zu lösen: Wie verbraucht eine Webanwendung geordnete kleine Informationsblöcke anstelle großer Informationsblöcke? Es gibt zwei Hauptanwendungsszenarien für diese Funktion.
Die Streams-API definiert drei Streams:
Lesbarer Stream: Ein Stream, der Datenblöcke über eine öffentliche Schnittstelle lesen kann. Daten gelangen intern von der zugrunde liegenden Quelle in den Stream und werden dann vom Verbraucher verarbeitet.
Beschreibbarer Stream: Ein Stream, in den Datenblöcke über eine öffentliche Schnittstelle geschrieben werden können. Der Produzent (Verbraucher) schreibt Daten in den Stream und die Daten werden intern an den zugrunde liegenden Datenslot (Senke) übertragen.
Konvertierungsstream: Er besteht aus zwei Streams: Der beschreibbare Stream wird zum Empfangen von Daten und der lesbare Stream zum Ausgeben von Daten verwendet. Bei diesen beiden Stream-Qualitätsprüfungen handelt es sich um Transformatoren, die Stream-Inhalte nach Bedarf prüfen und ändern können.
Die Web-Kryptografie-API beschreibt eine Reihe von Kryptografie-Tools, die standardisieren, wie JavaScript die Verschlüsselung auf sichere und herkömmliche Weise implementiert. Zu diesen Tools gehören das Generieren, Verwenden und Anwenden kryptografischer Schlüsselpaare, das Ver- und Entschlüsseln von Informationen sowie das zuverlässige Generieren von Zufallszahlen.
Viele Leute verwenden Math.random()
wenn sie Zufallszahlen generieren müssen. Diese Methode ist im Browser als Pseudozufallszahlengenerator (PRNG, PseudoRandom Number Generator) implementiert. Das sogenannte Pseudo bezieht sich auf den Prozess der Generierung von Werten, der nicht wirklich zufällig ist. Die von PRNG generierten Werte simulieren lediglich zufällige Merkmale. Der PRNG des Browsers verwendet keine echte Zufallsquelle, sondern wendet nur einen festen Algorithmus auf einen internen Zustand an. Bei jedem Aufruf von Math.random()
wird dieser interne Zustand durch einen Algorithmus verändert und das Ergebnis in eine neue Zufallszahl umgewandelt. Beispielsweise verwendet der V8-Motor einen Algorithmus namens xorshift128+
um diese Modifikation durchzuführen.
Da der Algorithmus selbst fest ist und seine Eingabe nur der vorherige Zustand ist, wird auch die Zufallszahlenfolge bestimmt. xorshift128+
verwendet einen internen 128-Bit-Zustand und der Algorithmus ist so konzipiert, dass jeder Anfangszustand 2 128 -1 Pseudozufallswerte generiert, bevor er sich wiederholt. Diese Art von Schleife wird als Permutationsschleife bezeichnet, und die Länge dieser Schleife wird als Periode bezeichnet. Es ist offensichtlich, dass der Angreifer, wenn er den internen Zustand des PRNG kennt, die anschließend generierten Pseudozufallswerte vorhersagen kann. Wenn der Entwickler versehentlich PRNG verwendet, um einen privaten Schlüssel für die Verschlüsselung zu generieren, kann der Angreifer diese Funktion von PRNG verwenden, um den privaten Schlüssel zu berechnen.
Pseudozufallszahlengeneratoren werden hauptsächlich zur schnellen Berechnung scheinbar zufälliger Zahlen verwendet, eignen sich jedoch nicht für Verschlüsselungsalgorithmen. Zur Lösung dieses Problems werden kryptografisch sichere Pseudozufallszahlengeneratoren (CSPRNG, Cryptographically Secure PseudoRandom Number Generator) verwendet, die zusätzlich eine Entropie hinzufügen Eingaben wie das Testen der Hardwarezeit oder anderer Systemeigenschaften mit unvorhersehbarem Verhalten sind zwar nicht so schnell wie PRNG, der generierte Wert ist jedoch schwieriger vorherzusagen und kann zur Verschlüsselung verwendet werden.
Die Web Cryptography API führt CSPRNG ein, auf das über crypto.getRandomValues()
auf das globale Crypto
Objekt zugegriffen werden kann. Im Gegensatz zu Math.random()
das eine Gleitkommazahl zwischen 0 und 1 zurückgibt, schreibt getRandomValues()
Zufallswerte in das stereotype Array, das ihm als Parameter übergeben wird. Die Klasse des stereotypen Arrays spielt keine Rolle, da der zugrunde liegende Puffer mit Zufallsbits gefüllt wird.