Gemeinsame JavaScript-Versprechen, über die jeder Bescheid wissen sollte



Guten Tag, Freunde!

Ich präsentiere Ihnen die Übersetzung des Artikels von Apal Shah, "Häufige Javascript-Versprechungsfehler, die jeder Anfänger kennen und vermeiden sollte" .

Gemeinsame JavaScript-Versprechen, über die jeder Bescheid wissen sollte


Ich würde gerne etwas über diese Fehler erfahren, als ich JavaScript studiert habe und Versprechungen gemacht habe.

Immer wenn ein Entwickler mich anruft und sich beschwert, dass sein Code nicht funktioniert oder langsam ausgeführt wird, achte ich zuerst auf diese Fehler. Als ich vor 4 Jahren mit dem Programmieren anfing, wusste ich nichts über sie und war es gewohnt, sie zu ignorieren. Nachdem ich jedoch einem Projekt zugewiesen worden war, das ungefähr eine Million Anfragen in wenigen Minuten bearbeitet, hatte ich keine andere Wahl, als meinen Code zu optimieren (da wir eine Ebene erreicht hatten, in der eine weitere vertikale Skalierung unmöglich wurde).

In diesem Artikel möchte ich daher auf die häufigsten Fehler bei der Arbeit mit Versprechungen in JS eingehen, auf die viele nicht achten.

Fehler # 1. Verwenden eines Try / Catch-Blocks innerhalb eines Versprechens


Die Verwendung des Try / Catch-Blocks innerhalb des Versprechens ist unpraktisch, da Ihr Code, wenn er einen Fehler (innerhalb des Versprechens) auslöst, vom Fehlerbehandler des Versprechens selbst abgefangen wird.

Darum geht es hier:
new Promise((resolve, reject) => { try { const data = someFunction() //   resolve() } catch(e) { reject(e) } }) .then(data => console.log(data)) .catch(error => console.log(error)) 

Lassen Sie stattdessen den Code den Fehler außerhalb des Versprechens behandeln:
 new Promise((resolve, reject) => { const data = someFunction() //   resolve(data) }) .then(data => console.log(data)) .catch(error => console.log(error)) 

Dies funktioniert immer, außer wie unten beschrieben.

Fehler Nr. 2. Verwenden einer asynchronen Funktion in einem Versprechen


Bei Verwendung der asynchronen Funktion treten im Promise einige unangenehme Nebenwirkungen auf.

Angenommen, Sie möchten eine asynchrone Aufgabe ausführen, das Schlüsselwort „async“ zur Zusage hinzufügen und Ihr Code gibt einen Fehler aus. Jetzt können Sie diesen Fehler jedoch weder mit .catch () noch mit wait behandeln:
 //       new Promise(async() => { throw new Error('message') }).catch(e => console.log(e.message)) //        (async() => { try { await new Promise(async() => { throw new Error('message') }) } catch(e) { console.log(e.message) } })(); 

Jedes Mal, wenn ich in einem Versprechen auf eine asynchrone Funktion treffe, versuche ich, sie zu trennen. Und ich bekomme es in 9 von 10 Fällen. Dies ist jedoch nicht immer möglich. In diesem Fall haben Sie keine andere Wahl, als den Try / Catch-Block innerhalb des Versprechens zu verwenden (ja, dies widerspricht dem ersten Fehler, aber dies ist der einzige Ausweg):
 new Promise(async(resolve, reject) => { try { throw new Error('message') } catch(error) { reject(error) } }).catch(e => console.log(e.message)) //   async/await (async() => { try { await new Promise(async(resolve, reject) => { try { throw new Error('message') } catch(error) { reject(error) } }) } catch(e) { console.log(e.message) } })(); 

Fehler Nummer 3. Vergiss .catch ()


Dies ist einer der Fehler, von denen Sie nicht einmal vermuten, dass er vor Beginn des Tests auftritt. Oder wenn Sie ein Atheist sind, der nicht an Tests glaubt, stürzt Ihr Code in der Produktion mit Sicherheit ab. Denn die Produktion folgt streng dem Murphy'schen Gesetz , das besagt: "Alles, was schief gehen kann, wird schief gehen" (Sie können das so übersetzen: "Wenn etwas schief gehen kann, wird es passieren"; die Analogie auf Russisch ist das "Gesetz der Gemeinheit". - Ca.

Um den Code eleganter zu gestalten, können Sie das Versprechen in try / catch einschließen, anstatt .then (). Catch () zu verwenden.

Fehler Nr. 4. Verwenden Sie Promise.all () nicht


Promise.all () ist dein Freund.

Wenn Sie ein professioneller Entwickler sind, verstehen Sie wahrscheinlich, was ich sagen möchte. Wenn Sie mehrere nicht voneinander abhängige Versprechen haben, können Sie diese gleichzeitig ausführen. Standardmäßig werden Versprechungen parallel ausgeführt. Wenn Sie sie jedoch nacheinander ausführen müssen (mithilfe von wait), wird dies viel Zeit in Anspruch nehmen. Promise.all () kann die Latenz erheblich reduzieren:
 const {promisify} = require('util') const sleep = promisify(setTimeout) async function f1() { await sleep(1000) } async function f2() { await sleep(2000) } async function f3() { await sleep(3000) } //   (async() => { console.time('sequential') await f1() await f2() await f3() console.timeEnd('sequential') //  6  })(); 

Jetzt mit Promise.all ():
 (async() => { console.time('concurrent') await Promise.all([f1(), f2(), f3()]) console.timeEnd('concurrent') //  3  })(); 

Fehler Nr. 5. Missbräuchliche Verwendung von Promise.race ()


Promise.race () beschleunigt Ihren Code nicht immer.

Es mag seltsam erscheinen, aber es ist es wirklich. Ich sage nicht, dass Promise.race () eine nutzlose Methode ist, aber Sie müssen klar verstehen, warum Sie sie verwenden.

Sie können beispielsweise Promise.race () verwenden, um den Code auszuführen, nachdem Sie eines der Versprechen gelöst haben. Dies bedeutet jedoch nicht, dass die Ausführung des Codes, der den Versprechungen folgt, unmittelbar nach der Lösung eines dieser Versprechungen beginnt. Promise.race () wartet auf die Auflösung aller Versprechungen und gibt erst dann den Stream frei:
 const {promisify} = require('util') const sleep = promisify(setTimeout) async function f1() { await sleep(1000) } async function f2() { await sleep(2000) } async function f3() { await sleep(3000) } (async() => { console.time('race') await Promise.race([f1(), f2(), f3()]) })(); process.on('exit', () => { console.timeEnd('race') //  3 ,    ! }) 

Fehler Nr. 6. Missbrauch von Versprechungen


Versprechen verlangsamen den Code, also missbrauchen Sie sie nicht.

Häufig müssen Entwickler eine lange .then () - Kette verwenden, damit ihr Code besser aussieht. Sie werden keine Zeit haben, ein Auge zu blinzeln, da diese Kette zu lang wird. Um die negativen Konsequenzen einer solchen Situation visuell überprüfen zu können, ist es notwendig (weiter werde ich ein wenig vom Originaltext abweichen, um den Vorgang detaillierter als im Artikel zu beschreiben - ca. Trans):

1) erstelle eine script.js Datei mit folgendem Inhalt (mit zusätzlichen Versprechungen):
 new Promise((resolve) => { //  ,    const user = { name: 'John Doe', age: 50, } resolve(user) }).then(userObj => { const {age} = userObj return age }).then(age => { if(age > 25) { return true } throw new Error('Age is less than 25') }).then(() => { console.log('Age is greater than 25') }).catch(e => { console.log(e.message) }) 

2) Öffnen Sie die Befehlszeile (für Windows-Benutzer: Um die Befehlszeile im Ordner mit der gewünschten Datei zu öffnen, halten Sie die Umschalttaste gedrückt, klicken Sie mit der rechten Maustaste und wählen Sie "Befehlsfenster öffnen" aus.) Führen Sie script.js mit dem folgenden Befehl aus (Node muss installiert sein. js):
 node --trace-events-enabled script.js 

3) Node.js erstellt eine Protokolldatei (in meinem Fall node_trace.1.txt) im Ordner mit dem Skript.

4) Öffne Chrome (weil es nur darin funktioniert), gib "chrome: // tracing" in die Adressleiste ein.

5) Klicken Sie auf Laden, laden Sie die von Node.js erstellte Protokolldatei.

6) Öffnen Sie die Registerkarte Versprechen.

Wir sehen ungefähr Folgendes:


Grüne Blöcke sind Versprechungen, die jeweils mehrere Millisekunden dauern. Je mehr Versprechungen gemacht werden, desto länger werden sie durchgeführt.

Wir schreiben script.js neu:
 new Promise((resolve, reject) => { const user = { name: 'John Doe', age: 50, } if(user.age > 25) { resolve() } else { reject('Age is less than 25') } }).then(() => { console.log('Age is greater than 25') }).catch(e => { console.log(e.message) }) 

Wiederholen Sie den "Trace".

Wir sehen folgendes:


Es gibt weniger grüne Blöcke (Versprechungen), was bedeutet, dass die Code-Ausführungszeit reduziert wurde.

Daher sollten Sie mehrere Versprechungen nur verwenden, wenn Sie asynchronen Code ausführen müssen.

Danke für die Aufmerksamkeit. Schönes Wochenende! Über Kommentare würde ich mich freuen.

Source: https://habr.com/ru/post/de484466/


All Articles