返回 jQuery 承诺的 Vuex 动作不起作用,.fail 不是函数

Posted

技术标签:

【中文标题】返回 jQuery 承诺的 Vuex 动作不起作用,.fail 不是函数【英文标题】:Vuex action returning jQuery promise doesn't work, .fail is not a function 【发布时间】: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 【参考方案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

以上是关于返回 jQuery 承诺的 Vuex 动作不起作用,.fail 不是函数的主要内容,如果未能解决你的问题,请参考以下文章

Redux-Thunk - 异步动作创建者承诺和链接不起作用

为啥 router.push 不起作用? [Vue 3] [Vuex 4]

带有承诺的 Redux-thunk 不起作用

VueJS从Vuex返回值不起作用

导入自定义 axios 实例时 Vuex 模块不起作用

将模块重构为单独的文件时,Vuex 4模块不起作用