How to know if a function is async?

后端 未结 8 797
别跟我提以往
别跟我提以往 2020-12-01 00:55

I have to pass a function to another function, and execute it as a callback. The problem is that sometimes this function is async, like:

async function() {
          


        
8条回答
  •  独厮守ぢ
    2020-12-01 01:54

    TL;DR

    Short answer: Use instaceof after exposing AsyncFunction - see below.

    Long answer: Don't do that - see below.

    How to do it

    You can detect whether a function was declared with the async keyword

    When you create a function, it shows that it's a type Function:

    > f1 = function () {};
    [Function: f1]
    

    You can test it with the instanceof operator:

    > f1 instanceof Function
    true
    

    When you create an async function, it shows that it's a type AsyncFunction:

    > f2 = async function () {}
    [AsyncFunction: f2]
    

    so one might expect that it can be tested with instanceof as well:

    > f2 instanceof AsyncFunction
    ReferenceError: AsyncFunction is not defined
    

    Why is that? Because the AsyncFunction is not a global object. See the docs:

    • https://developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/AsyncFunction

    even though, as you can see, it's listed under Reference/Global_Objects...

    If you need easy access to the AsyncFunction then you can use my unexposed module:

    • https://www.npmjs.com/package/unexposed

    to get either a local variable:

    const { AsyncFunction } = require('unexposed');
    

    or to add a global AsyncFunction alongside other global objects:

    require('unexposed').addGlobals();
    

    and now the above works as expected:

    > f2 = async function () {}
    [AsyncFunction: f2]
    > f2 instanceof AsyncFunction
    true
    

    Why you shouldn't do it

    The above code will test whether the function was created with the async keyword but keep in mind that what is really important is not how a function was created but whether or not a function returns a promise.

    Everywhere where you can use this "async" function:

    const f1 = async () => {
      // ...
    };
    

    you could also use this:

    const f2 = () => new Promise((resolve, reject) => {
    });
    

    even though it was not created with the async keyword and thus will not be matched with instanceof or with any other method posted in other answers.

    Specifically, consider this:

    const f1 = async (x) => {
      // ...
    };
    
    const f2 = () => f1(123);
    

    The f2 is just f1 with hardcoded argument and it doesn't make much sense to add async here, even though the result will be as much "async" as f1 in every respect.

    Summary

    So it is possible to check if a function was created with the async keyword, but use it with caution because you when you check it then most likely you're doing something wrong.

提交回复
热议问题