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)
最终使用了 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)