返回承诺的 Vuex 操作永远不会解析或拒绝

Posted

技术标签:

【中文标题】返回承诺的 Vuex 操作永远不会解析或拒绝【英文标题】:Vuex action which returns a promise never resolves or rejects 【发布时间】:2018-12-02 00:41:47 【问题描述】:

我正在尝试使用 Vuex 在我的 VueJS 应用程序中构建我的 API 服务。我正在重构一些东西以集中错误处理、清理等。我遇到的问题是通过我的函数调用正确链接 Promise。

在根级别,我有一个 BaseService 类,它只是使用 AXios(不是完整类)发出 API 请求:

export abstract class BaseService 
  protected readonly API: AxiosInstance; // Full init left out

  protected deleteItem(url: string): Promise<any> 
    return new Promise((resolve, reject) => 
      this.API.delete(url)
        .then((response: any) => 
          resolve(response);
        )
        .catch((error: any) => 
          this.handleError(error); // Local function that logs error
          reject(error);
        );
    );
  

然后我在上面有一层,通过组装请求 URL 和处理数据来管理 API 的不同功能:

class CompanyService extends BaseService 
  private constructor() 
    super();
  

  public delete(id: number): Promise<any> 
    return this.deleteItem(`$this.baseUrl/api/companies/$id`);
  

然后在我的 Vuex 操作中,我调用 companyService 删除函数:

const action = 
  COMPANY_DELETE(context: any, id: number) 
    return new Promise((resolve, reject) => 
      companyService // Instance of CompanyService
        .delete(id)
        .then((response: any) => 
          console.log(response); // This logs successfully
          resolve(response);
        )
        .catch((error: any) => 
          console.log(error); // This logs successfully
          reject(error);
        );
    );
  
;

如我的 cmets 所示,两个控制台日志已成功完成。当我到达调用此操作的组件时,就会出现此问题:

this.$store
  .dispatch("company/COMPANY_DELETE", company.id) // Namespaced
  .then((response: any) => 
    console.log(response); // Never gets called
  )
  .catch((error: any) => 
    console.log(error); // Never gets called
  );

永远不会调用这两个控制台日志。我在这里做错了什么?

【问题讨论】:

不完全了解您的代码库是"company/COMPANY_DELETE" 正确的操作名称吗?不应该是"COMPANY_DELETE" 是的,存储模块是命名空间的。那是正确的名字。在重构之前,我没有 Base 和 Company 服务,所以一切都在行动中并且按预期工作。调用动作的组件没有改变。重构的目的是整理存储,提高可重用性和错误处理能力。 您的控制台中是否收到任何错误消息? 在构建期间或控制台中没有错误消息或警告。 最好在您的功能旅程中放置几个​​断点,以查看它在哪个点中断。 【参考方案1】:

使用 axios 演示操作的小示例,无需额外的承诺包装...

const store = new Vuex.Store(
	state: 
  	followers: 0
  ,
  mutations: 
  	updateFollowers(state, followers)
    	state.followers = followers;
    
  ,
  actions: 
    getFollowers(commit) 
        return axios.get('https://api.github.com/users/octocat').then( (response) => 
        	commit("updateFollowers", response.data.followers);
          return "success!!!";
        );
    
  
)

Vue.component('followers', 
  template: '<div>Followers:  computedFollowers </div>',
  created () 
    this.$store.dispatch('getFollowers').then( (result) => 
    	console.log(result);
    );
  ,
  computed: 
  	computedFollowers() 
    	return store.state.followers;
    
  
);

const app = new Vue(
	store,
  el: '#app'
)
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<div id="app">
  <followers></followers>
</div>

【讨论】:

这就是答案。我不需要 Vuex Action 中的额外承诺。但是,对于我的特定用例,我还需要支持捕获传播。我已经更新了对我有用的解决方案。感谢您的帮助!【参考方案2】:

最终的工作是像Void Ray 所说的那样删除额外的 Promise。但是,在我的特定用例中,我还需要支持错误传播。因此,以下操作包含我需要进行的修复。

const action = 
  COMPANY_DELETE(context: any, id: number) 
    return companyService // Instance of CompanyService
      .delete(id)
      .then((response: any) => 
        console.log(response);
      )
      .catch((error: any) => 
        console.log(error);
        throw error; // Needed to continue propagating the error
      );
  ,
;

【讨论】:

以上是关于返回承诺的 Vuex 操作永远不会解析或拒绝的主要内容,如果未能解决你的问题,请参考以下文章

承诺要么永远不会被调用,要么被拒绝(Parse JS SDK)

当用户选择“不再询问”并禁用地理定位时,React native `Geolocation.getCurrentPosition` 承诺将永远不会被解决/拒绝

如何保证承诺不会拒绝的API用户

如何保证承诺不会拒绝的API用户

异常被承诺链吞噬

我如何测试返回承诺或拒绝的函数 - Jasmine 和 Karma