【问题标题】:Vuex action returning jQuery promise doesn't work, .fail is not a function返回 jQuery 承诺的 Vuex 动作不起作用,.fail 不是函数
【发布时间】:2021-02-25 03:38:24
【问题描述】:

我有一个像这样的 vuex 动作

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

在我的 vue 组件中

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

抛出错误:

未捕获的类型错误:this.myAction(...).fail 不是函数

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

【问题讨论】:

  • 如果myAction 未能显式返回 jQuery 承诺(它将返回隐式包装承诺),您所描述的将会发生。您是否测试了上面的简化示例并且仍然得到错误?只是想知道您的实际操作是否与示例足够不同。
  • 这正是我尝试过的,this.myAction().catch(...) 有效,但 this.myAction().fail 无效
  • 我正在使用 vuex 3.4.0

标签: jquery vue.js vuejs2 vuex jquery-deferred


【解决方案1】:

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

所以在过去,$.Deferred 承诺能够溜过,因为它有一个 .then 方法,该方法返回一个带有 .fail 方法的 $ 承诺对象。但现在它被封装在原生 Promise 中。


注册操作

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

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

store.dispatch.prototype

store.dispatch.prototype 确实发生了变化。它过去只返回.then 方法:

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

但现在它总是返回一个 promise 包装器:

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

而且包装器也不会费心返回内部结果。看来 Vuex 已经决定规范化操作的返回值,以保证它是一个原生的 Promise。

【讨论】:

  • 这是我在测试一些东西时使用的fiddle
猜你喜欢
  • 2016-06-07
  • 2019-09-03
  • 2019-07-30
  • 1970-01-01
  • 2021-02-02
  • 2017-08-03
  • 2017-04-29
  • 2018-12-02
  • 1970-01-01
相关资源
最近更新 更多