Ember 在 Action 中集中处理错误

Ember centralised error handling within an Action

在一个 Ember controller 中,我有许多 actions 在商店中执行数据事件(创建更新和删除)。

这些请求中的每一个都有重复多次的相同错误处理逻辑。有没有办法集中这个错误逻辑?

  1. 鉴于此逻辑将被许多路由使用,Ember 中哪个位置最适合它运行?
  2. 如何保留上下文,以便 this 仍然可以向 DOM 发送 toast 类型的消息?

这是我现在的例子

createEntryRecord() {
  // This action is a 'create' button on a modal
  set(this, 'isLoadingModal', true);  // shows loading spinner
  let dbid = this.get('dbidModal');
  let type = this.get('entryModalType');

  this.get('store').createRecord('my-store', {
    type,
    dbid
  })
  .save()
  .then((record) => {
    get(this, 'flashMessages').success(`Created`);  // Toast message
  })
  .catch((e) => {
    // Begin of the error handling logic
    let errors = get(e, 'errors');
    if (errors.length) {
      errors.forEach(err => {
        let field = err.source.pointer.split("/").pop();
        get(this, 'flashMessages').danger(`${field}: ${err.detail}`);
      });
    } else {
      let message = get(e, 'message');
      get(this, 'flashMessages').danger(`${message}`);
    }
  })
  .finally(() => {
    set(this, 'isLoadingModal', false);  // stop the loading spinner
    set(this, 'isEntryModalShown', false);
  });
},

我建议使用 Ember 的对象模型 Mixins
首先,您为所有模型创建一个通用的 Mixin:

// app/mixins/flashing-model.js
import Mixin from '@ember/object/mixin';
import { inject as service } from '@ember/service';

export default Mixin.create({
    flashMessages: service(), // can be accessed via this.get('flashMessages')
    save(...args) {
        const superSavePromise = this._super(...args);
        superSavePromise.then(() => {
            // your positive logic
        }).catch(e => {
            // your negative logic
        });
        return superSavePromise;
    }
});

然后将其包含在每个模型中。例如:

// app/models/some-model.js
import FlashingModel from '{your-app-name}/mixins/flashing-model';
import DS from 'ember-data'
export default DS.Model.extend(FlashingModel, {
    // ...
});

之后你可以编辑你的控制器:

this.get('store').createRecord('my-store', {
    type,
    dbid
})
.save()
.finally(() => {
    // ...
});

所以关于你的问题:
1. Ember Mixins(在 app/mixins 目录下)是存放通用逻辑的好地方。
2. 实施上述解决方案时,您实际上不需要保留控制器的 this 上下文,因为 flashMessages service 已注入每个模型。因此,您可以在 save 方法的上下文中访问该服务,即模型的 this