简体   繁体   中英

What is the (potential) drawback of using async functions everywhere?

I am learning Javascript. This may sound like a crazy idea but I don't find clear answers on Google. Can I just replace all my regular functions/methods with async function everywhere? I mean there seems to be no downsides to this and it makes things so much simpler. Where the situation only involves synchronous steps, you just don't use await and it will work just like normal functions. Easy!

Personally I find having to distinguish async functions and normal functions unnecessarily burdensome. It's like driving a manual transmission car, where the car itself could easily handle the gearing by itself.

Am I missing something here?

async functions always return Promises . This means that anytime you're not dealing with something asynchronous, you would have to convert the returned Promise into a value before you could use it. For example:

 const return4 = async () => 4; console.log(4 + return4());

Instead, you would have to use the (unnecessarily wordy):

 const return4 = async () => 4; (async () => { console.log(4 + await return4()); })();

(or call .then on the return4 call before using it)

If return4 was not async , on the other hand, of course console.log(4 + return4()); alone would work just fine.

Another problem with async functions is that transpiling them to ES5 code (which allows for compatibility with obsolete browsers like IE) requires regenerator-runtime , which is very heavyweight. For example, transpiling the following single line with Babel:

const foo = async () => console.log('async!');

When you plug it into the repl , you get:

"use strict";

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }
  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}

function _asyncToGenerator(fn) {
  return function() {
    var self = this,
      args = arguments;
    return new Promise(function(resolve, reject) {
      var gen = fn.apply(self, args);
      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
      }
      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
      }
      _next(undefined);
    });
  };
}

var foo =
  /*#__PURE__*/
  (function() {
    var _ref = _asyncToGenerator(
      /*#__PURE__*/
      regeneratorRuntime.mark(function _callee() {
        return regeneratorRuntime.wrap(function _callee$(_context) {
          while (1) {
            switch ((_context.prev = _context.next)) {
              case 0:
                return _context.abrupt("return", console.log("async!"));

              case 1:
              case "end":
                return _context.stop();
            }
          }
        }, _callee);
      })
    );

    return function foo() {
      return _ref.apply(this, arguments);
    };
  })();

which also depends on regeneratorRuntime already being included in the script, which is 700-something lines of code that you can see here .

On less powerful systems, this can result in a not-insignificant performance hit. This is why some (such as with the AirBNB style guide) prefer to never use async functions, even if they make the asynchronous control flow of the script clearer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM