I am wondering if it is possible to dynamically create an async function like this:
new Function('await Promise.resolve()');
Expectedly, the previous code throw:
Uncaught SyntaxError: await is only valid in async function
                Yes, you can get a reference to the non-global AsyncFunction constructor to dynamically create async functions.
You get a reference to the AsyncFunction constructor like this:
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
The signature of the AsyncFunction constructor is:
AsyncFunction(arg0?, arg1?, ...args?, functionBody: string);
NOTE: The AsyncFunction contructor is not global (like Function is), the only way to get a reference to it is via the prototype of an async function(){} instance, as shown above and in the MDN docs.
    const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
    
    const myAsync = new AsyncFunction(`return true`);
    
    const result = await myAsync(); // true
    
    myAsync().then((result) => {
        // result is true
    });
The example above is equivalent to:
    const myAsync = async () => {
        return true;
    };
    const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
    
    // Define two named arguments: inValue, delay
    const asyncFn = new AsyncFunction('inValue', 'delay', `return new Promise((resolve) => {
        setTimeout(() => {resolve(inValue)}, delay);
    });`);
    
    // resolves to 'hello' after 100ms
    const result = await asyncFn('hello', 100);
    
    // After 200ms the promise will be resolved with the value 'world'
    asyncFn('world', 200).then((result) => {
        console.log(result);
    });
The example above is equivalent to:
    const asyncFn = async (inValue, delay) => {
        return new Promise((resolve) => {
            setTimeout(() => {resolve(inValue)}, delay);
        });
    };
Another cool thing is that the parameters are allowed to use defaults, destructuring, and rest parameters.
    const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
    
    // Define defaults for inValue and delay
    const asyncFn = new AsyncFunction('inValue = "Hello"', 'delay = 100', `return new Promise((resolve) => {
        setTimeout(() => {resolve(inValue)}, delay);
    });`);
    
    // resolves to 'hello' after 100ms (because we defined default parameters)
    const result = await asyncFn();
    
    // resolves to 'world' after 200ms
    const result = await asyncFn('world', 200);
Just note that it might be insecure to construct a function like this if the delay value were to come from an untrusted source, like user input.
    const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
    
    function createAsync(delay){
        return new AsyncFunction('inValue', `return new Promise((resolve) => {
            setTimeout(() => {resolve(inValue)}, ${delay});
        });`);
    }
    
    const asyncFn = createAsync(100);
    const asyncFn2 = createAsync(200);
    
    // After 100ms this will resolve 'hello'
    await result1 = asyncFn('hello');
    
    // After 200ms this will resolve 'world'
    await result2 = asyncFn2('world');
This is roughly equivalent to:
    function createAsync(delay){
        return async (inValue) => {
            return new Promise((resolve) => {
                setTimeout(() => {resolve(inValue)}, delay);
            };
        };
    }
    
    const asyncFn = createAsync(100);
    
    // After 100ms this will resolve 'hello'
    await result1 = asyncFn('hello');
    
    // After 100ms this will resolve 'world'
    await result2 = asyncFn('world');
And remember that you can use await inside the dynamically created async function :)
Note that the same security considerations apply to the async function constructor as the Function constructor and eval().
If you are constructing a new function with content received from an untrusted source then your script or application may be vulnerable to injection attacks.
Don't use new Function(). I'd personally say NEVER use it unless you're a compiler because:
Creating functions dynamically in js simply requires you to declare a function expression:
function functionMaker() {
    return function () {};
}
Therefore creating an async function dynamically is simply:
function asyncMaker() {
     return async function () {};
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With