Reputation: 42464
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
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.
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);
}
...
}
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