Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

196
Vistas
¿Por qué await eval('`${await foo("xxx")}`') genera un error?

Antes de que me llamen por usar eval()... SÍ, sé que eval === es malvado y del diablo y nunca debería usarse. Esa NO es la pregunta aquí. Lo crea o no, tengo un caso válido de la vida real en el que tiene mucho sentido usar eval, de hecho, no hay otra forma de lograr el resultado que necesito.

A continuación se muestra un fragmento de código con 4 casos. Los primeros tres funcionan exactamente como se esperaba. Los dos primeros llaman a una función asíncrona en un literal de plantilla. El tercero y el cuarto almacenan el literal de la plantilla como una cadena y luego evalúan la cadena. En el caso (no 3) donde no se usa await, como se esperaba, se devuelve la promesa. Sin embargo, el problema es el caso 4. Produce un error y, por mi vida, no puedo entender por qué o cómo solucionarlo.

Espero que alguien más inteligente que yo pueda encontrar una solución para que el caso 4 aún pueda evaluarse sin arrojar un error (primer premio) o explicar por qué no funciona o no se puede hacer.

 async function foo(str) { return str.toUpperCase(); } async function bar() { const str1 = `${foo("xxx")}`; console.log("STR1:", str1); // Output: STR1: [object Promise] const str2 = `${await foo("xxx")}`; console.log("STR2:", str2); // Output: STR2: XXX const str3 = '`${foo("xxx")}`'; console.log("STR3:", await eval(str3)); //Output STR3: [object Promise] const str4 = '`${await foo("xxx")}`'; console.log("STR4:", await eval(str4)); // undefined:1 // `${await foo("xxx")}` // ^^^^^^ // Output: SyntaxError: Missing } in template expression } bar();

about 4 years ago · Juan Pablo Isaza
3 Respuestas
Responde la pregunta

0

A continuación se describe otra forma de hacerlo funcionar, básicamente separando la espera de la promesa de la construcción de la cadena (más o menos), utilizando plantillas etiquetadas :

 async function foo(str) { return str.toUpperCase(); } async function asyncFooTmpl(strings, asyncExpr) { return `${strings[0]}${await asyncExpr}${strings[1]}`; } async function bar() { const str1 = `${foo("xxx")}`; console.log("STR1:", str1); // Output: STR1: [object Promise] const str2 = `${await foo("xxx")}`; console.log("STR2:", str2); // Output: STR2: XXX const str3 = '`${foo("xxx")}`'; console.log("STR3:", await eval(str3)); //Output STR3: [object Promise] const str4 = 'asyncFooTmpl`${foo("xxx")}`'; console.log("STR4:", await eval(str4)); //Output STR4: XXX } bar();

Esto transfiere la propiedad de esperar la promesa de bar a asyncFooTmpl , lo que permite que se produzca la cadena.

Dicho esto, sería necesario que escriba funciones para cada plantilla que tenga, o que cree una función que haga que el manejo de plantillas etiquetadas sea más manejable.

Como aceptaste esto y escribiste tu propia respuesta combinando mi comentario, creé un violín de un ejemplo algo más mejorado si tienes curiosidad.

about 4 years ago · Juan Pablo Isaza Denunciar

0

Probé muchos enfoques y, aunque a menudo me acerqué a una solución, nunca funcionó del todo. La solución propuesta por Heretic Monkey funcionó a las mil maravillas. Literalmente copié su código para "genericizar" la función de plantilla y funcionó. No necesitaba cambiar nada.

En caso de que alguien más esté buscando una solución como esta, estoy publicando el ejemplo completo que preparé para demostrarme a mí mismo que funciona. El ejemplo es un poco largo, pero quería mostrar un uso práctico y real de la solución para que sea más fácil de entender para los demás.

 async function foo(str) { await sleep(2000); console.log(`foo caled with ${str}`); return str.toUpperCase(); } function sleep(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } async function resolveTemplate(strings, ...maybePromises) { const final = []; for (let i = 0; i < strings.length; i++) { final.push(strings[i]); final.push(Object.prototype.toString.call(maybePromises[i]).includes("Promise") ? await maybePromises[i] : maybePromises[i]); } return final.join(""); } const person = { firstName: "Joe", lastName: "Blogs", Age: 23 }; async function bar() { let str = 'resolveTemplate`{ "name": "${foo(person.firstName.concat(" ",person.lastName))}", "age": ${person.Age}, "sex": "${foo("male")}" }`'; console.log("STR4:", await eval(str)); //Output STR4: { "name": "JOE BLOGS", "age": 23, "sex": "MALE" } } bar(); console.log("Done");

about 4 years ago · Juan Pablo Isaza Denunciar

0

No está relacionado con eval directamente. Simplemente no puede usar await fuera de la función async .

Esto dará como resultado el mismo error:

 const x = `${await Promise.resolve()}`

Envolver la llamada en asíncrono IIFE resuelve el problema:

 async function foo(str) { return str.toUpperCase(); } async function bar() { const x = '`${(async () => await foo("xxx"))()}`' eval(x) } bar();

Prueba de que await no se puede usar en eval en la función async , porque eval no es tan simple

 async function foo(str) { return str.toUpperCase(); } async function bar() { try { const x = ' await foo("xxx")`' eval(x) } catch (e) { console.error(e) } } bar();

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda