MatAtBread / fast-async

605 stars 21 forks source link

incorrect code when this is used in async function #61

Closed sormy closed 5 years ago

sormy commented 5 years ago

This code:

  public async loadBundle() {
    return new Promise((resolve, reject) => {
      if (this.xhr) {
        this.xhr.abort()
        this.xhr = undefined
      }

      this.xhr = $.ajax({
        url: "some url",

        dataType: "script",

        success: () => {
          resolve()
        },

        error: (jqXHR, textStatus, errorThrown) => {
          reject()
        },
      })
    })
  }

converted to:

    loadBundle(bundleID) {
      return new Promise(function ($return, $error) {
        return $return(new Promise((resolve, reject) => {
          if (this.xhr) {
            this.xhr.abort();
            this.xhr = undefined;
          }

          this.xhr = $.ajax({
            url: "some url",
            dataType: "script",
            success: () => {
              resolve()
            },
            error: (jqXHR, textStatus, errorThrown) => {
              reject()
            }
          });
        }));
      });

and this is always undefined here because return new Promise(function ($return, $error) { steals this.

package.json:

    "@babel/core": "^7.1.6",
    "@babel/plugin-proposal-class-properties": "^7.1.0",
    "@babel/plugin-proposal-object-rest-spread": "^7.0.0",
    "@babel/plugin-transform-react-constant-elements": "^7.0.0",
    "@babel/plugin-transform-react-inline-elements": "^7.0.0",
    "@babel/preset-env": "^7.1.6",
    "@babel/preset-react": "^7.0.0",
    "@babel/preset-typescript": "^7.1.0",
    "fast-async": "^7.0.6",

babel.config.js:

{
  compact: false,
  presets: [
    ['@babel/preset-env', {
      targets: ['Since 2018'],
      exclude: ['transform-regenerator']
    }],
    ['@babel/preset-react', { development: isDev }],
    ['@babel/preset-typescript', { isTSX: true, allExtensions: true }]
  ],
  plugins: [
    '@babel/proposal-class-properties',
    '@babel/proposal-object-rest-spread',
    'module:fast-async',
    'add-module-exports',
    'inline-react-svg',
    'add-react-displayname',
  ]
}
matAtWork commented 5 years ago

It works for me using the link below. I'm guessing some other babel transform is munging the code and stripping the .$asyncbind which ensures this is set correctly.

As a point of information, there is no point in returning a Promise from an async function, or indeed declaring it async - you can just return a Promise and await on that

Output:

function loadBundle() {
    return (function ($return, $error) {
        return $return(new Promise((resolve, reject) => {
            if (this.xhr) {
                this.xhr.abort();
                this.xhr = undefined;
            }
            this.xhr = $.ajax({
                url: "some url",
                dataType: "script",
                success: () => {
                    resolve();
                },
                error: (jqXHR, textStatus, errorThrown) => {
                    reject();
                }
            });
        }));
    }).$asyncbind(this, 0);
}

http://nodent.mailed.me.uk/#async%20function%20loadBundle()%20%7B%0A%20%20%20%20return%20new%20Promise((resolve%2C%20reject)%20%3D%3E%20%7B%0A%20%20%20%20%20%20if%20(this.xhr)%20%7B%0A%20%20%20%20%20%20%20%20this.xhr.abort()%0A%20%20%20%20%20%20%20%20this.xhr%20%3D%20undefined%0A%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20this.xhr%20%3D%20%24.ajax(%7B%0A%20%20%20%20%20%20%20%20url%3A%20%22some%20url%22%2C%0A%0A%20%20%20%20%20%20%20%20dataType%3A%20%22script%22%2C%0A%0A%20%20%20%20%20%20%20%20success%3A%20()%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20resolve()%0A%20%20%20%20%20%20%20%20%7D%2C%0A%0A%20%20%20%20%20%20%20%20error%3A%20(jqXHR%2C%20textStatus%2C%20errorThrown)%20%3D%3E%20%7B%0A%20%20%20%20%20%20%20%20%20%20reject()%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%7D)%0A%20%20%20%20%7D)%0A%20%20%7D~options~%7B%22mode%22%3A%22lazyThenables%22%2C%22promiseType%22%3A%22Zousan%22%2C%22noRuntime%22%3Afalse%2C%22es6target%22%3Atrue%2C%22wrapAwait%22%3Afalse%2C%22spec%22%3Afalse%7D

sormy commented 5 years ago

Hi, still trying to figure out why $asyncbind is not in output. However, having async explicitly defined for function is very convenient since it helps static analyzers to warn if I forgot to add await before function call.

sormy commented 5 years ago

Seems like fast-async needs two plugins fromenv preset to be disabled to work well. I guess it could be added to documentation for the plugin. There are no issues if these two transforms are disabled.

{
  "presets": [
    ["@babel/env", {
      "exclude": ["transform-regenerator", "transform-async-to-generator"]
    }]
  ],
  "plugins": [
    "module:fast-async"
  ]
}
MatAtBread commented 5 years ago

Thanks for the update. Babel is a moving target, and this repo is pretty much in maintenance only. If you want to do a PR for the README, I'd be happy to accept it.