返回 jQuery promise 的 Vuex 操作不起作用,.fail 不是函数

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

我有一个像这样的 vuex 动作

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

在我的 vue 组件中

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

抛出错误:

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

代码工作正常,但是一旦我更新了我的 npm modules/vue-cli/webpack 等,问题就出现了。另一点是,如果我将 .fail 更改为 .catch 那么它就可以正常工作。但问题是为什么 .fail 不起作用?

从 Vuex 3.4.0 开始,操作总是 return 原生承诺。在过去的版本中,Vuex 只检查一个动作是否 returned 一个 thennable 对象,即任何带有 .then 属性 的对象。如果不是,它将 action return 值包装在一个新的 promise 中。但如果是这样,它只是 returned 对象而不包装它,假设它是一个 promise。从 3.4.0 开始,Vuex 甚至包装了 thennable 对象。

所以在过去,$.Deferred promise 能够被忽略,因为它有一个 .then 方法,其中 return 是一个 $ promise 对象 .fail方法。但现在它被包裹在原生承诺中。


registerAction

如果您检查 Vuex 源代码,您会发现 registerAction 没有从 3.3.0 更改为 3.4.0。这是 non-thennable return 值被包装在 promises 中的地方。它没有改变:

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

store.dispatch.prototype

但是 store.dispatch.prototype 确实发生了变化。它曾经只是 return .then 方法:

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

但现在它总是 return 是一个承诺包装器:

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

并且包装器也不会理会 return 内部结果。看来 Vuex 已经决定规范化操作的 return 值,以保证它是原生的承诺。