coure2011
coure2011

Reputation: 42464

Vuex action returning jQuery promise doesn't work, .fail is not a function

I have a vuex action like this

myAction() {
    const deferred = $.Deferred();
    setTimeout(() => deferred.resolve(), 3000);
    return deferred.promise();
}

in my vue component

myMethod() {
    this.myAction().fail(() => ...do something...);
}

throwing error:

Uncaught TypeError: this.myAction(...).fail is not a function

The code was working fine, but issue appeared once I updated my npm modules/vue-cli/webpack etc. Another point is if I change .fail to .catch then it works fine. But the question is why .fail is not working?

Upvotes: 2

Views: 488

Answers (1)

Dan
Dan

Reputation: 63089

Beginning with Vuex 3.4.0, actions always return a native promise. In past versions, Vuex only checked whether an action returned a thennable object, i.e. anything with .then property. If not, it wrapped the action return value in a new promise. But if so, it simply returned the object without wrapping it, assuming it was a promise. Starting with 3.4.0, Vuex wraps even thennable objects.

So in the past, the $.Deferred promise was able to slip by, because it has a .then method which returns a $ promise object with a .fail method. But now it gets wrapped in a native promise.


registerAction

If you inspect the Vuex source, you see that registerAction didn't change from 3.3.0 to 3.4.0. This is where non-thennable return values are wrapped in promises. It hasn't changed:

function registerAction (store, type, handler, local) {
  ...
  if (!isPromise(res)) {
    res = Promise.resolve(res);
  }
  ...
}

store.dispatch.prototype

But store.dispatch.prototype did change. It used to just return the .then method:

return result.then(function (res) {
  ...
})

But now it always returns a promise wrapper:

return new Promise(function (resolve, reject) {
  result.then(function (res) {  // Doesn't return the inner promise either
    ...
  })
})

And the wrapper doesn't bother to return the inner result either. It seems Vuex has decided to normalize the return value of actions so that it's guaranteed to be a native promise.

Upvotes: 1

Related Questions