【问题标题】:Vuex action which returns a promise never resolves or rejects返回承诺的 Vuex 操作永远不会解析或拒绝
【发布时间】: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 服务,所以一切都在行动中并且按预期工作。调用动作的组件没有改变。重构的目的是整理存储,提高可重用性和错误处理能力。
  • 您的控制台中是否收到任何错误消息?
  • 在构建期间或控制台中没有错误消息或警告。
  • 最好在您的功能旅程中放置几个​​断点,以查看它在哪个点中断。

标签: javascript vue.js promise axios vuex


【解决方案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
      });
  },
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-03
    • 2015-12-25
    • 1970-01-01
    • 2019-07-30
    • 2016-03-21
    • 2016-05-06
    • 1970-01-01
    • 2019-11-29
    相关资源
    最近更新 更多