如何在ember

时间:2015-08-18 17:29:52

标签: ember.js

我想要的是:全局处理不同http错误(401,404,500)的错误处理。发生http错误的地方或时间不重要。

到目前为止,我在应用程序路由中实现了一个错误操作,该操作将在路由model挂钩上的任何适配器错误上调用。这很好。

当我在record.save()等其他环境中使用记录时,未涵盖的内容就是这种情况。在那里,我需要单独处理承诺上的错误。

此外,我不想只有一个默认的错误处理程序,但更像是一个后备。

好的,在谈论太多之前,让我们举例说明我的用例。

申请路线

应用程序错误操作应该是默认/回退错误处理程序。

actions: {
  error: function(error) {
    var couldHandleError = false;

    if (error.errors) {
      switch (error.errors[0].status) {
        case '401':
          // User couldn't get authenticated.
          // Redirect handling to login.

          couldHandleError = true;
          break;
        case '404':
        case '500':
          // Something went unexpectedly wrong.
          // Let's show the user a message

          couldHandleError = true;
          break;
      }
    }

    // return true if none of the status code was matching
    return !couldHandleError;
  }
}

某些路线

在这种情况下,将调用应用程序错误操作。

model: function() {
  return this.store.findAll('post');
}

某些控制器

在这种情况下,不会调用应用程序错误操作。

(我知道,以下代码可能没有意义,但它只是为了说明我的要求)

this.store.findRecord('post', 123);

其他一些控制器

在这个例子中,没有调用应用程序错误操作,因为我在这里使用自己的处理程序(catch())。 但正如您在评论中所看到的,我确实希望对404以外的所有状态代码使用默认处理程序。

this.store.findRecord('post', 123).catch(function(reason) {
  if (reason.errors[0].status === '404') {
    // Do some specific error handling for 404
  } else {
    // At this point I want to call the default error handler
  }
});

有没有一种清洁和认可的方法来实现这一目标?我希望我能把问题告诉你。

2 个答案:

答案 0 :(得分:14)

我想我有最后的解决方案,我希望与您分享。基本上我采纳了那些人评论我的问题的想法,并扩展他们以满足我的需要。

首先,我用主逻辑创建了一个mixin。因为我希望它尽可能通用,它区分a)控制器/路由和b)jquery /适配器错误。因此,从您调用它的位置以及您的错误对象最初是来自jquery Ajax请求还是ember适配器并不重要。

import Ember from 'ember';

export default Ember.Mixin.create({

  ajaxError: function(error) {
    if (!error) {
      Ember.Logger.warn('No (valid) error object provided! ajaxError function must be called with the error object as its argument.');
      return;
    }

    // Depending whether the mixin is used in controller or route
    // we need to use different methods.
    var transitionFunc = this.transitionToRoute || this.transitionTo,
        couldHandleError = false;

    switch (this._getStatusCode(error)) {
      case 401:
        transitionFunc.call(this, 'auth.logout');
        couldHandleError = true;
        break;
      case 404:
      case 500:
        // Here we trigger a service to show an server error message.
        // This is just an example and currently not the final implementation.
        // this.get('notificationService').show(); 
        couldHandleError = true;
        break;
    }

    // For all other errors just log them.
    if (!couldHandleError) {
      Ember.Logger.error(error);
    }
  },

  _getStatusCode: function(error) {
    // First check for jQuery error object
    var status = error.status;

    // Check for ember adapter error object if it's not a jquery error
    if (!status && error.errors && error.errors[0].status) {
      status = parseInt(error.errors[0].status);
    }

    return status;
  },

});

接下来,我重新打开了一些类(在app.js中)以使这个功能全局可用:

import AjaxErrorMixin from 'app/mixins/ajax-error';

Ember.Route.reopen(AjaxErrorMixin);
Ember.Controller.reopen(AjaxErrorMixin);

Ember.Component.reopen({
  _actions: {
    // Passing ajaxError per default
    ajaxError: function(error) {
      this.sendAction('ajaxError', error);
    }
  }
});

最后,我在应用程序路径中添加了一些操作:

actions: {
  error: function(error) {
    this.send('ajaxError', error);
  },

  ajaxError: function(error) {
    this.ajaxError(error);
  },
}

为什么我有两个动作做同样的事情?好吧,error动作是在路由模型钩子上的错误上调用的。我可以继续使用该操作,但在我明确调用此操作的应用程序的其余部分中,我想要一个更有意义的名称。因此,我还创建了ajaxError动作。你肯定可以坚持一个动作。

现在你可以在任何地方使用它:

路线/控制器

this.ajaxError(error);

组件

this.sendAction('ajaxError', error);

当然,您还需要将操作传递出应用程序路径要处理的组件:

{{some-component ajaxError="ajaxError"}}

这也适用于嵌套组件。您不需要在component.js文件中进一步显式发送此操作,因为我们重新打开了Component并将此操作传递给。

我希望我能帮助其他人实现这一目标。也欢迎任何反馈。

答案 1 :(得分:5)

您可以尝试对这些事件做一些事情(在app初始化之前将这些行放在app.js中):

Ember.onerror = function (error) {
  console.log('Ember.onerror handler', error.message);
};

Ember.RSVP.on('error', function (error) {
  console.log('Ember.RSVP error handler', error);
});

Ember.Logger.error = function (message, cause, stack) {
  console.log('Ember.Logger.error handler', message, cause, stack);
};

我从https://raygun.io/blog/2015/01/javascript-error-handling-ember-js/了解了它们,你可能会在那里找到一些细节。