Les promesses JavaScript courantes sont importantes pour tout le monde



Bonjour mes amis!

Je vous présente la traduction de l ' article d' Apal Shah, "Erreurs Javascript communes de promesse que chaque débutant devrait connaître et éviter . "

Les promesses JavaScript courantes sont importantes pour tout le monde


J'aimerais connaître ces erreurs lorsque j'ai étudié JavaScript et les promesses.

Chaque fois qu'un développeur m'appelle et se plaint que son code ne fonctionne pas ou s'exécute lentement, je fais tout d'abord attention à ces erreurs. Quand j'ai commencé à programmer il y a 4 ans, je ne les connaissais pas et j'avais l'habitude de les ignorer. Cependant, après avoir été affecté à un projet qui traite environ un million de demandes en quelques minutes, je n'ai pas eu d'autre choix que d'optimiser mon code (car nous avons atteint un niveau où une nouvelle mise à l'échelle verticale est devenue impossible).

Par conséquent, dans cet article, je voudrais parler des erreurs les plus courantes lorsque vous travaillez avec des promesses dans JS, auxquelles beaucoup ne prêtent pas attention.

Erreur # 1. Utilisation d'un bloc try / catch dans une promesse


L'utilisation d'un bloc try / catch à l'intérieur d'une promesse n'est pas pratique, car si votre code génère une erreur (à l'intérieur d'une promesse), il sera intercepté par le gestionnaire d'erreurs de la promesse elle-même.

Voici de quoi il s'agit:
new Promise((resolve, reject) => { try { const data = someFunction() //   resolve() } catch(e) { reject(e) } }) .then(data => console.log(data)) .catch(error => console.log(error)) 

Au lieu de cela, laissez le code gérer l'erreur en dehors de la promesse:
 new Promise((resolve, reject) => { const data = someFunction() //   resolve(data) }) .then(data => console.log(data)) .catch(error => console.log(error)) 

Cela fonctionnera toujours, sauf comme décrit ci-dessous.

Erreur n ° 2. Utilisation d'une fonction asynchrone dans une promesse


Lorsque vous utilisez la fonction asynchrone, certains effets secondaires désagréables se produisent dans la promesse.

Supposons que vous décidiez d'effectuer une tâche asynchrone, ajoutez le mot clé "async" à la promesse et que votre code génère une erreur. Cependant, maintenant vous ne pouvez pas gérer cette erreur avec .catch () ou attendre:
 //       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) } })(); 

Chaque fois que je rencontre une fonction asynchrone dans une promesse, j'essaie de les séparer. Et je l'obtiens dans 9 cas sur 10. Mais ce n'est pas toujours possible. Dans ce cas, vous n'avez pas d'autre choix que d'utiliser le bloc try / catch à l'intérieur de la promesse (oui, cela contredit la première erreur, mais c'est la seule issue):
 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) } })(); 

Erreur numéro 3. Oubliez .catch ()


Il s'agit d'une de ces erreurs que vous ne soupçonnez même pas d'exister avant le début des tests. Ou, si vous êtes un athée qui ne croit pas aux tests, votre code se bloquera certainement en production . Parce que la production suit strictement la loi de Murphy , qui stipule: "Tout ce qui peut mal tourner va mal" (vous pouvez traduire ceci: "Si quelque chose peut mal tourner, cela se produira"; l'analogie en russe est la "loi de la méchanceté" - env.

Pour rendre le code plus élégant, vous pouvez encapsuler la promesse dans try / catch au lieu d'utiliser .then (). Catch ().

Erreur n ° 4. N'utilisez pas Promise.all ()


Promise.all () est votre ami.

Si vous êtes un développeur professionnel, vous comprenez probablement ce que je veux dire. Si vous avez plusieurs promesses qui ne dépendent pas les unes des autres, vous pouvez les exécuter en même temps. Par défaut, les promesses sont exécutées en parallèle, mais si vous devez les exécuter séquentiellement (à l'aide de l'attente), cela prendra beaucoup de temps. Promise.all () peut réduire considérablement la latence:
 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  })(); 

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

Erreur n ° 5. Utilisation incorrecte de Promise.race ()


Promise.race () ne rend pas toujours votre code plus rapide.

Cela peut sembler étrange, mais c'est vraiment le cas. Je ne dis pas que Promise.race () est une méthode inutile, mais vous devez comprendre clairement pourquoi vous l'utilisez.

Par exemple, vous pouvez utiliser Promise.race () pour exécuter le code après avoir résolu l'une des promesses. Mais cela ne signifie pas que l'exécution du code suivant les promesses commencera immédiatement après la résolution de l'un d'entre eux. Promise.race () attendra que toutes les promesses soient résolues et ne libérera que le flux:
 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 ,    ! }) 

Erreur n ° 6. Abus de promesses


Les promesses ralentissent le code, alors n'en abusez pas.

Souvent, vous devez voir les développeurs utiliser une longue chaîne .then () pour améliorer l'apparence de leur code. Vous n'aurez pas le temps de cligner des yeux, car cette chaîne devient trop longue. Afin de vérifier visuellement les conséquences négatives d'une telle situation, il est nécessaire (plus loin je m'écarterai un peu du texte original afin de décrire le processus plus en détail que dans l'article - env. Trans):

1) créez un fichier script.js avec le contenu suivant (avec des promesses supplémentaires):
 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) ouvrez la ligne de commande (pour les utilisateurs de Windows: pour ouvrir la ligne de commande dans le dossier contenant le fichier souhaité, maintenez la touche Maj enfoncée, cliquez avec le bouton droit, sélectionnez «Ouvrir la fenêtre de commande»), exécutez script.js à l'aide de la commande suivante (le nœud doit être installé. js):
 node --trace-events-enabled script.js 

3) Node.js crée un fichier journal (dans mon cas node_trace.1.txt) dans le dossier avec le script;

4) ouvrez Chrome (car il ne fonctionne que dans celui-ci), entrez «chrome: // tracing» dans la barre d'adresse;

5) cliquez sur Charger, chargez le fichier journal créé par Node.js;

6) ouvrez l'onglet Promise.

Nous voyons quelque chose comme ceci:


Les blocs verts sont des promesses, dont chacune prend plusieurs millisecondes. Par conséquent, plus les promesses seront nombreuses, plus elles seront tenues.

Nous réécrivons script.js:
 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) }) 

Répétez la «trace».

Nous voyons ce qui suit:


Il y a moins de blocs verts (promesses), ce qui signifie que le temps d'exécution du code a été réduit.

Ainsi, vous ne devez utiliser plusieurs promesses que si vous devez exécuter du code asynchrone.

Merci de votre attention. Bon week-end! Je serai heureux de tout commentaire.

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


All Articles