await is only valid in async function - eval in async
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"];
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 + "})()")
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();
})
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
}