Las promesas comunes de JavaScript son importantes para todos



Buen dia amigos!

Le presento la traducción del artículo de Apal Shah, "Errores comunes de Promesa de Javascript que todo principiante debe saber y evitar" .

Las promesas comunes de JavaScript son importantes para todos


Me gustaría saber acerca de estos errores cuando estudié JavaScript y promesas.

Cada vez que un desarrollador me llama y se queja de que su código no funciona o se ejecuta lentamente, en primer lugar presto atención a estos errores. Cuando comencé a programar hace 4 años, no los conocía y estaba acostumbrado a ignorarlos. Sin embargo, después de ser asignado a un proyecto que procesa alrededor de un millón de solicitudes en unos minutos, no tuve más remedio que optimizar mi código (ya que alcanzamos un nivel en el que la escala vertical adicional se hizo imposible).

Por lo tanto, en este artículo me gustaría hablar sobre los errores más comunes al trabajar con promesas en JS, a lo que muchos no prestan atención.

Error # 1. Usando un bloque try / catch dentro de una Promesa


Usar el bloque try / catch dentro de la promesa no es práctico, porque si su código arroja un error (dentro de la promesa), será interceptado por el controlador de errores de la promesa misma.

De esto se trata:
new Promise((resolve, reject) => { try { const data = someFunction() //   resolve() } catch(e) { reject(e) } }) .then(data => console.log(data)) .catch(error => console.log(error)) 

En cambio, deje que el código maneje el error fuera de la promesa:
 new Promise((resolve, reject) => { const data = someFunction() //   resolve(data) }) .then(data => console.log(data)) .catch(error => console.log(error)) 

Esto siempre funcionará, excepto como se describe a continuación.

Error No. 2. Usando una función asincrónica dentro de una Promesa


Cuando se usa la función asincrónica, se producen algunos efectos secundarios desagradables dentro de Promise.

Suponga que decide realizar alguna tarea asincrónica, agregue la palabra clave "async" a la promesa y su código arroje un error. Sin embargo, ahora no puede manejar este error con .catch () o esperar:
 //       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) } })(); 

Cada vez que encuentro una función asincrónica dentro de una promesa, trato de separarlos. Y lo obtengo en 9 de cada 10 casos. Sin embargo, esto no siempre es posible. En este caso, no tiene más remedio que usar el bloque try / catch dentro de la promesa (sí, esto contradice el primer error, pero esta es la única salida):
 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) } })(); 

Error número 3. Olvídate de .catch ()


Este es uno de esos errores que ni siquiera sospechas que existe hasta que comienzan las pruebas. O, si usted es un ateo que no cree en las pruebas, su código ciertamente se bloqueará en la producción . Debido a que la producción sigue estrictamente la ley de Murphy , que establece: "Todo lo que puede salir mal saldrá mal" (puede traducir esto: "Si algo puede salir mal, sucederá"; la analogía en ruso es la "ley de la maldad" - aprox.

Para hacer que el código sea más elegante, puede ajustar la promesa en try / catch en lugar de usar .then (). Catch ().

Error No. 4. No use Promise.all ()


Promise.all () es tu amigo.

Si eres un desarrollador profesional, probablemente entiendas lo que quiero decir. Si tiene varias promesas que no dependen unas de otras, puede ejecutarlas al mismo tiempo. De manera predeterminada, las promesas se ejecutan en paralelo, sin embargo, si necesita ejecutarlas secuencialmente (usando waitit), tomará mucho tiempo. Promise.all () puede reducir considerablemente la latencia:
 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  })(); 

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

Error No. 5. Uso incorrecto de Promise.race ()


Promise.race () no siempre hace que su código sea más rápido.

Puede parecer extraño, pero realmente lo es. No estoy diciendo que Promise.race () sea un método inútil, pero debes entender claramente por qué lo estás usando.

Por ejemplo, puede usar Promise.race () para ejecutar el código después de resolver cualquiera de las promesas. Pero esto no significa que la ejecución del código siguiendo las promesas comenzará inmediatamente después de la resolución de uno de ellos. Promise.race () esperará a que se resuelvan todas las promesas y solo entonces lanzará la transmisión:
 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 ,    ! }) 

Error No. 6. Abuso de promesas


Las promesas hacen que el código sea más lento, así que no abuses de ellas.

A menudo hay que ver a los desarrolladores utilizando una larga cadena .then () para que su código se vea mejor. No tendrá tiempo para parpadear, ya que esta cadena se vuelve demasiado larga. Para verificar visualmente las consecuencias negativas de tal situación, es necesario (además me desviaré un poco del texto original para describir el proceso con más detalle que en el artículo - aprox. Trans):

1) cree un archivo script.js con el siguiente contenido (con promesas adicionales):
 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) abra la línea de comando (para usuarios de Windows: para abrir la línea de comando en la carpeta con el archivo deseado, mantenga presionada la tecla Mayús, haga clic con el botón derecho, seleccione "Abrir ventana de comando"), ejecute script.js usando el siguiente comando (el nodo debe estar instalado. js):
 node --trace-events-enabled script.js 

3) Node.js crea un archivo de registro (en mi caso node_trace.1.txt) en la carpeta con el script;

4) abra Chrome (porque solo funciona en él), ingrese “chrome: // tracing” en la barra de direcciones;

5) haga clic en Cargar, cargue el archivo de registro creado por Node.js;

6) abra la pestaña Promesa.

Vemos algo como lo siguiente:


Los bloques verdes son promesas, cada uno de los cuales tarda varios milisegundos en completarse. Por lo tanto, mientras más promesas sean, más tiempo se cumplirán.

Reescribimos 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) }) 

Repita el "rastro".

Vemos lo siguiente:


Hay menos bloques verdes (promesas), lo que significa que el tiempo de ejecución del código se ha reducido.

Por lo tanto, debe usar varias promesas solo si necesita ejecutar algún código asincrónico.

Gracias por su atencion ¡Que tengan un buen fin de semana! Estaré encantado de cualquier comentario.

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


All Articles