await 仅在异步函数中有效 - eval 在异步中

Ran*_*gel 10 javascript asynchronous eval node.js

我想在异步函数中 eval() 一些代码行。虽然下面的代码没问题,

async function foo()
{
  await foo1();
  await foo2();
}
Run Code Online (Sandbox Code Playgroud)

以下抛出错误:await 仅在 async 函数中有效

let ctxScript = 'await foo1(); await foo2();';
async function foo()
{
  eval( ctxScript );
}
Run Code Online (Sandbox Code Playgroud)

我怎么能处理这个?我的 foo() 应该是异步的,因为它是 Puppeteter 控制器功能

Erm*_*mir 22

foo()不一定是async,因为这对 的执行上下文没有影响eval。相反,一个可能的解决方案是将您的 ctxScript 包装在一个自执行的异步函数中,如下所示:eval("(async () => {" + ctxScript + "})()")


Mer*_*n04 11

如果您希望能够等待评估,可以使用以下命令:

await Object.getPrototypeOf(async function() {}).constructor("your code here")();
Run Code Online (Sandbox Code Playgroud)

这使用了AsyncFunction构造函数。MDN 有一个页面描述了使用它和使用之间的区别eval

注意:使用 AsyncFunction 构造函数创建的异步函数不会为其创建上下文创建闭包;它们始终是在全局范围内创建的。

运行它们时,它们只能访问自己的局部变量和全局变量,而不能访问调用 AsyncFunction 构造函数的作用域中的变量。

这与将 eval 与异步函数表达式的代码一起使用不同。

这意味着,如果您希望评估代码能够访问变量,则需要将它们添加到globalThis

const testVar = "Hello world";
globalThis["testVar"] = testVar;
const result = await Object.getPrototypeOf(async function() {}).constructor(`
    console.log(testVar);
    await myAsyncFunc();
    return testVar;
`)();
// result will be "Hello world"
delete globalThis["testVar"];
Run Code Online (Sandbox Code Playgroud)


Ran*_*gel 5

最终使用了 Ermir 的回答:

let ctxScript = '(async () => {await foo1();await foo2();is_script_ended = true; })();';

async function foo()
{
  // a lot of code
  is_script_ended = false;
  eval( ctxScript );
  while(!is_script_ended){ await sleep(1000); }
  // a lot of code
}
Run Code Online (Sandbox Code Playgroud)

  • 在代码中睡觉从来都不是一个好主意。如果您的 eval 脚本失败,那么它将永远休眠,直到您重新启动系统。如果你真的想使用睡眠,也许可以将所有内容包装在 try catch 中,这样如果代码中断,你的睡眠就会停止。像“try {eval(ctxScript)} catch () {is_script_ending = true}”之类的东西 (3认同)