await is only valid in async function - eval in async

前端 未结 4 1869
北海茫月
北海茫月 2020-12-17 23:59

I want to eval() some lines of code inside of async function. While the following code is ok,

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


        
相关标签:
4条回答
  • 2020-12-18 00:42

    If you want to be able to await the eval you can use this:

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

    This uses the AsyncFunction constructor. MDN has a page on it which describes the differences between using it and using eval:

    Note: async functions created with the AsyncFunction constructor do not create closures to their creation contexts; they are always created in the global scope.

    When running them, they will only be able to access their own local variables and global ones, not the ones from the scope in which the AsyncFunction constructor was called.

    This is different from using eval with code for an async function expression.

    This means that if you have variables that you want your evaled code to be able to access, you need to add them to 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"];
    
    0 讨论(0)
  • 2020-12-18 00:51

    foo() should not necessarily be async, as that has no effect on the execution context of eval. Instead, a possible solution is to wrap your ctxScript in a self-executing async function, like so: eval("(async () => {" + ctxScript + "})()")

    0 讨论(0)
  • 2020-12-18 00:52

    Ended up using Ermir`s answer:

    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
    }
    
    0 讨论(0)
  • 2020-12-18 00:52

    If you want to dynamically call some async code in some larger function, then you can supply a callback that does this for you. This way you can call your function with different extra functionality by giving it different callback functions to execute:

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

    0 讨论(0)
提交回复
热议问题