El infierno de las devoluciones de llamadas también es un tema candente en las entrevistas técnicas, ya que pone a prueba la comprensión del desarrollador sobre el código asincrónico y su capacidad para refactorizar el código para mejorar su legibilidad y mantenibilidad.
La programación asincrónica es crucial en el desarrollo moderno de JavaScript, ya que permite la ejecución sin bloqueo y mejora el rendimiento, especialmente para operaciones vinculadas a E/S. Sin embargo, esta conveniencia a veces puede llevar a una condición conocida como "infierno de devolución de llamadas".
En este artículo, profundizaremos en:
Infierno de devolución de llamada, a menudo denominado "Pirámide de la perdición", ocurre cuando múltiples operaciones asincrónicas anidadas dependen unas de otras para ejecutarse en secuencia. Este escenario conduce a una maraña de devoluciones de llamadas profundamente anidadas, lo que hace que el código sea difícil de leer, mantener y depurar.
Ejemplo de devolución de llamada infernal:
getData(function(data) { processData(data, function(processedData) { saveData(processedData, function(response) { sendNotification(response, function(notificationResult) { console.log("All done!"); }); }); }); });
El código anterior realiza varias operaciones asincrónicas en secuencia. Si bien funciona, rápidamente se vuelve inmanejable si se agregan más tareas, lo que dificulta su comprensión y mantenimiento. La estructura anidada se asemeja a una pirámide, de ahí el término "Pirámide de la Perdición".
El infierno de las devoluciones de llamadas genera varios problemas:
Para mitigar los problemas del infierno de devolución de llamadas, Promises se utilizan en JavaScript. Las promesas representan la eventual finalización (o falla) de una operación asincrónica y le permiten escribir código limpio y más manejable. Las promesas simplifican el código - Con las promesas, la estructura anidada se aplana y el manejo de errores está más centralizado, lo que hace que el código sea más fácil de leer y mantener.
Así es como se vería el ejemplo anterior del infierno de devolución de llamada usando Promesas:
getData() .then(data => processData(data)) .then(processedData => saveData(processedData)) .then(response => sendNotification(response)) .then(notificationResult => { console.log("All done!"); }) .catch(error => { console.error("An error occurred:", error); });
Este enfoque elimina las devoluciones de llamadas profundamente anidadas. Cada bloque "luego" representa el siguiente paso en la cadena, lo que hace que el flujo sea mucho más lineal y más fácil de seguir. El manejo de errores también está centralizado en el bloque 'catch'.
Las promesas tienen tres estados posibles:
Un objeto Promise proporciona los métodos '.then()' y '.catch()' para manejar escenarios de éxito y fracaso.
function getData() { return new Promise((resolve, reject) => { // Simulating an async operation (e.g., API call) setTimeout(() => { const data = "Sample Data"; resolve(data); }, 1000); }); } getData() .then(data => { console.log("Data received:", data); }) .catch(error => { console.error("Error fetching data:", error); });
En el código anterior, la función 'getData()' devuelve una Promesa. Si la operación asincrónica tiene éxito, la promesa se cumple con los datos, de lo contrario se rechaza con error.
Una de las principales ventajas de las Promesas es que se pueden encadenar. Esto permite secuenciar operaciones asincrónicas sin anidar.
function fetchData() { return new Promise((resolve, reject) => { setTimeout(() => resolve("Data fetched"), 1000); }); } function processData(data) { return new Promise((resolve, reject) => { setTimeout(() => resolve(`${data} and processed`), 1000); }); } function saveData(data) { return new Promise((resolve, reject) => { setTimeout(() => resolve(`${data} and saved`), 1000); }); } fetchData() .then(data => processData(data)) .then(processedData => saveData(processedData)) .then(result => { console.log(result); // Output => Data fetched and processed and saved }) .catch(error => console.error("Error:", error));
Al encadenar Promesas, el código se vuelve plano, más legible y más fácil de mantener.
Si bien las promesas son una mejora significativa con respecto a las devoluciones de llamada, aún pueden resultar engorrosas con cadenas extensas. Aquí es donde entra en juego async/await.
La sintaxis Async/await nos permite escribir código asincrónico de una manera que se asemeja al código sincrónico. Hace que su código sea más limpio y más fácil de razonar.
Usando Async/Await:
async function performOperations() { try { const data = await getData(); const processedData = await processData(data); const response = await saveData(processedData); const notificationResult = await sendNotification(response); console.log("All done!"); } catch (error) { console.error("Error:", error); } } performOperations();
En el código anterior:
- La palabra clave 'async' se utiliza para definir una función asincrónica.
- 'await' pausa la ejecución de la función hasta que la promesa se resuelva o rechace, lo que hace que el código parezca sincrónico.
- El manejo de errores es mucho más sencillo, utilizando un único bloque 'try-catch'.
- Async/await elimina el infierno de devolución de llamadas y las largas cadenas de promesas, lo que lo convierte en la forma preferida de manejar operaciones asincrónicas en JavaScript moderno.
Infierno de devolución de llamada es un problema común en JavaScript que surge cuando se trabaja con múltiples operaciones asincrónicas. Las devoluciones de llamadas profundamente anidadas generan código que no se puede mantener y es propenso a errores. Sin embargo, con la introducción de Promises y async/await, los desarrolladores ahora tienen formas de escribir código más limpio, más manejable y escalable.
Promises aplana las devoluciones de llamadas anidadas y centraliza el manejo de errores, mientras que async/await simplifica aún más la lógica asincrónica al hacerla parecer sincrónica. Ambas técnicas eliminan el caos del infierno de las devoluciones de llamadas y garantizan que su código siga siendo legible, incluso a medida que crece en complejidad.
Identificadores de redes sociales
Si este artículo te resultó útil, no dudes en conectarte conmigo en mis canales de redes sociales para obtener más información:
- GitHub: [AmanjotSingh0908]
- LinkedIn: [Amanjot Singh Saini]
- Twitter: [@AmanjotSingh]
¡Gracias por leer!
Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.
Copyright© 2022 湘ICP备2022001581号-3