Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

193
Views
¿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 answers
Answer question

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 Report

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!