简体   繁体   中英

callback function not executes unexpectedly

I have this function to execute a callback after the fade out animation of the textarea finishes:

function inputReset() {
  return new Promise((resolve) => {
    if (lastExtend === true) {
      return resolve();
    };
    console.log('inside inputReset');
    const textarea = $("textarea").first();
    textarea.fadeOut(1500, "swing", async() => {
      console.log('inside callback');
      await textareaAnimeEnded(textarea);
      console.log('after await textareaAnimeEnded(textarea)');
      return resolve();
    });
  });

  function textareaAnimeEnded(textarea) {
    console.log('inside textareaAnimeEnded');
    inputClear();
    textarea.fadeIn(0);
    Dots.show();
    return new Promise(resolve => setTimeout(() => resolve(), 500));
  }
}

But unexpectedly I only see the console.log('inside inputReset'); and although the fade out animation occures but I never get to the callback function (we never reach console.log('inside callback'); )

What I'm missing?

The confusion here is due to jQuery version mismatches. JQuery's isFunction check was updated in version 3.3.0 to accept async functions and generators.

fadeOut and other animation functions check the type of the callback argument. If it isn't a "function" (by jQuery's definition), then jQuery assumes no callback was passed.

The callback passed to fadeOut must therefore satisfy jQuery's definition of a function. And, unfortunately, before v3.3.0 that definition didn't include async functions or generators.

The check jQuery did before v3.3.0 was basically:

({}).toString.call(maybeFunction) === '[object Function]'

(actual algorithm here and here and usedhere by fadeOut and all other animations)

We can see that async functions and generators don't pass this check:

({}).toString.call(() => {}) // '[object Function]'
({}).toString.call(async () => {}) // '[object AsyncFunction]'
({}).toString.call(function*() {}) // '[object GeneratorFunction]'

However, with the new check added in v3.3.0:

typeof maybeFunction === 'function'

all of these pass:

typeof (() => {}) // 'function'
typeof (async () => {}) // 'function'
typeof function*() {} // 'function'

This is why in versions < 3.3.0 you see the animation working, but your async callback function is not called. JQuery doesn't recognize it as a function. In fact, if you omit the easing parameter, jQuery tries to set the passed async callback function as the animation's easing, which breaks jQuery:

textarea.fadeOut(2000, async () => {})
// jquery.js:6515 Uncaught (in promise) TypeError: jQuery.easing[this.easing] is not a function

for more nitty gritty details, read on:


The changelog in question is here :

Update isFunction to handle unusual-@@toStringTag input

The jQuery PR responsible for this change is here :

Generators and async functions are still functions, and we can recognize them with typeof

Most notably this line :

return jQuery.type( obj ) === "function"

got changed to (simplified):

return typeof obj === "function"

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