await仅在异步功能中有效-异步中的eval

时间:2019-05-17 13:10:31

标签: javascript node.js asynchronous eval

我想在异步函数中对一些代码行进行eval()。可以执行以下代码,

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

以下内容引发错误:等待仅在异步函数中有效

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

我该如何处理? 我的foo()应该是异步的,因为它是Puppetteer控制器功能

5 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

如果要在某个较大的函数中动态调用一些异步代码,则可以提供一个回调函数来为您执行此操作。通过这种方式,您可以通过为其执行不同的回调函数来调用具有其他额外功能的函数:

// 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();
})

答案 2 :(得分:1)

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

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

这使用AsyncFunction构造函数。 MDN具有a page on it,其中描述了使用它和使用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"];

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

在传递给 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();
}