0

在我的 Backbone/Marionette 应用程序的每个经过身份验证的请求(GET、POST 等)中,我必须附加一个 accessToken。

我将此 accessToken 和 expireDate 存储在 localStorage 中。

要检查 accessToken 是否过期,我调用此方法:user.checkToken()。如果已过期,该方法会使用对我的后端的 POST 请求更新 accessToken。

我应该把这张支票放在哪里?我的意思是,在应用程序的哪个部分?

我应该重写我的 on Backbone.sync方法还是使用ajax.setup "beforeSend" ?

提前感谢您的建议/想法。

4

2 回答 2

2

覆盖您的模型的sync()功能并做任何您需要做的事情。例如:

var MyModel = Backbone.Model.extend({
  sync: function() {
    // Put your code here

    Backbone.Model.prototype.sync.apply(this, arguments);
  }
});

编辑#1:

不确定你从哪里得到user(以及其他变量),但它是:

var MyModel = Backbone.Model.extend({
  sync: function() {
    user.checkToken().done(_.bind(function(){
       Backbone.Model.prototype.sync.apply(this, [ method, model, options ]);
     });
  }, this);
});
于 2013-07-01T17:35:46.487 回答
2

Backbone 对 ajax 请求使用 jQuery(有关可能与 Zepto 一起使用的解决方案的注释),因此您可以使用(如 Edward 建议的那样)jQuery.ajaxPrefilter

我为这个任务做了一点测试,如果有任何问题,请告诉我:

function tokenIsExpired() {
    return true;
}

function createPromiseFunction(method, jqXHRsource, jqXHR) {
    return function() {
        jqXHRsource[method] = function(f) {
            if (f) {
                jqXHR[method] = function() {
                    f.apply(this, arguments);
                };
            }

            return this;
        };
    }
}

function updateToken() {
    return $.ajax({
        url: '',
        method: 'GET',
        data: {some:'data', here:'yes'},
        success: function() {
            // update the token sir
            console.log('token call done')
        },
        skipTokenCheck: true // required
    });
}


$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
    /*
     * check if token is expired every time a new ajax request is made
     * if it is expired, aborts the current requests, updated the token
     * and eventually does the original request again.
     */

    if (!options.skipTokenCheck && tokenIsExpired()) {
        // at this point no callback should have be added to the promise object

        var methodsNames = [
            'done',
            'always',
            'fail',
            'progress',
            'then'
        ];

        var methods = {};

        // copy the callbacks when they're added to the old request

        for (var i = 0; i < methodsNames.length; i++) {
            var name = methodsNames[i];

            createPromiseFunction(name, jqXHR, methods)();
        };

        jqXHR.abort();

        // TODO: error checks
        updateToken().done(function() {
            console.log('done');
            var newReq = $.ajax($.extend(originalOptions, {skipTokenCheck: true}));

            for (var i = 0; i < methodsNames.length; i++) {
                var name = methodsNames[i];
                var f = methods[name];

                if (f) {
                    newReq[name](f);
                }
            };
        });
    }
});

var p = $.get('.');

p.done(function() { console.log(arguments); }).fail(function() {
    console.log('fail');
});

看起来 ajaxPrefilter 不适用于 Zepto。或者,您可以使用ajaxBeforeSend事件。

在 beforeSend 函数中返回 false 将取消请求。

应该很容易适应我上面发布的代码。

于 2013-07-07T18:15:57.410 回答