繁体   English   中英

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

[英]await is only valid in async function - eval in async

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

async function foo()
{
  await foo1();
  await foo2();
}

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

let ctxScript = 'await foo1(); await foo2();';
async function foo()
{
  eval( ctxScript );
}

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

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

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

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

await Object.getPrototypeOf(async function() {}).constructor("your code here")();

这使用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"];

如果你想在一些更大的函数中动态调用一些异步代码,那么你可以提供一个回调来为你做这件事。 通过这种方式,您可以通过给它不同的回调函数来调用具有不同额外功能的函数来执行:

 // some sample async functions var resolveAfter2Seconds = function() { console.log("starting slow promise -> "); return new Promise(resolve => { setTimeout(function() { resolve("slow"); console.log("<- slow promise is done"); }, 2000); }); }; var resolveAfter1Second = function() { console.log("starting fast promise ->"); return new Promise(resolve => { setTimeout(function() { resolve("fast"); console.log("<- fast promise is done"); }, 1000); }); }; //a function that accepts a callback and would await its execution async function foo(callback) { console.log("-- some code --"); await callback(); console.log("-- some more code --"); } //calling with an async function that combines any code you want to execute foo(async () => { await resolveAfter2Seconds(); await resolveAfter1Second(); })

这是另一种无需睡觉或做任何复杂事情的方法。

在传递给eval()代码中,将整个代码包装在另一个异步函数中,并将其设置为某个变量,例如EVAL_ASYNC 然后在运行eval(ctxScript) ,运行该异步函数await EVAL_ASYNC

let ctxScript = 'var EVAL_ASYNC = async function() {await foo1(); await foo2();}';
async function foo()
{
  eval( ctxScript );
  await EVAL_ASYNC();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM