Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

189
Visualizações
¿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 Respostas
Responde à pergunta

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 Relatório

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda