简体   繁体   English

错误回调后重新调用Backbone.Sync方法

[英]Re-call Backbone.Sync method after error callback

I am working on an application where if our Bearer token has expired and we get a 401 back from the server. 我在一个应用程序上工作,如果我们的Bearer令牌已过期并且我们从服务器取回401。 We want to call an endpoint /api/newToken and set that new bearer token to the cookie (which is later added to the headers) and then re call the URL that was being called when the error (401 status) occurred. 我们要调用端点/api/newToken并将该新的承载令牌设置为cookie(稍后将其添加到标头中),然后重新调用在发生错误(401状态)时被调用的URL。

We overwrote the backbone sync method 我们改写了骨干同步方法

var sync_mixin = {
        // `preSync` is a useful hook from which events can be published,
        //      and options / model may be modified.
        preSync: function (method, model, options) {},

        // override sync to:
        //  - call preSync first
        //  - because tastypie and backbone disagree on whether delete should have trailing slash
        sync: function (method, model, options) {
            model.preSync(method, model, options);
            options = options || {};
            options.headers = getAuthHeaders()

            // Add trailing slash to backbone model views
            var _url = _.isFunction(model.url) ?  model.url() : model.url;
            // Missing the case where there is a query string on a detail view here: /v7.0/<resource>/<id>?key=val
            _url += _url.charAt(_url.length - 1) == '/' || _url.indexOf('?') != -1 ? '' : '/';

            options = _.extend(options, {
                url: _url,
                model: model
            });

            if (method.toLowerCase() === 'delete') {
                if (!options.url) {
                    options.url = _.result(model, 'url').replace(/\/$/, "") + '/';
                }
            }

            return Backbone.sync.apply(this, arguments);
        }
    };

    Backbone.Model = Backbone.Model.extend(sync_mixin);

Ideally I want to handle the error in once place (and not within each model file). 理想情况下,我想一次处理错误(而不是在每个模型文件中)。 What I am trying to accomplish is when I get the error on sync, call the api endpoint get the new token, set it to the cookie and re call the original sync method with the new cookie as the token. 我要完成的工作是,当我收到同步错误时,调用api端点获取新令牌,将其设置为cookie,然后使用新cookie作为令牌重新调用原始sync方法。 Here is what I have tried, but I am running into maximum call stack errors. 这是我尝试过的方法,但是遇到了最大的调用堆栈错误。 I added this code inside the sync function above 我在上面的同步功能中添加了此代码

            options.error = function(xhr, status, thrown) {
              if(xhr.status === 401 || xhr.status === 403){
                  $.cookies.set("auth-token", '6fe36b69cdac549339850a5aa2f148b470dc2e0e');
                  Backbone.sync.apply(this.model, arguments);
              }
            }

Any suggestions on how to resolve this issue? 有关如何解决此问题的任何建议? I can get anything else that is needed. 我还能得到其他所需的东西。

I got this working. 我工作了。 Tte max call stack error was due to me accidentally adding request back to the options which made a recursive call. Tte max调用堆栈错误是由于我不小心将请求添加回进行递归调用的选项。

Here is my code that allows for the recall of sync 这是我的代码,允许召回同步

    var errorHandler = options.error;
    options.error = function(xhr) {
      var errorHandlerArgs = arguments;
      if ((xhr.status === 401 || xhr.status === 0) && $this.ajaxTried < 3) {
          $this.ajaxTried++;
          //call refresh_bearer/ URL 
          $.ajax({
            url: "/api/refresh_bearer/",
            headers: args[2].headers
          }).done(function (data) {
            args[2].headers = getAuthHeaders()
            Backbone.sync.apply($this, args);
          });
      } else {
          $this.ajaxTried = 0;
          errorHandler.apply($this, errorHandlerArgs);
      }
    };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM