Backbone:中止以前的路由器回调执行

时间:2014-11-19 11:54:12

标签: javascript user-interface backbone.js backbone-routing

假设我的页面上有2个链接:

<a href="#A">Link A</a>
<a href="#B">Link B</a>

我使用骨干路由器来处理应用内页面导航。

在路由链接&#39;#A&#39;上,我已经注册了一个监听器A和类似的监听器B,用于&#39; #B&#39; listenerA和listenerB都在后台执行一些繁重的任务。

现在,让我们假设用户点击了“链接A&#39;并且只需几毫秒的间隔,点击“链接B”即可。

因此,当listenerA完成其执行时,只有那时listenerB才开始执行,因为单个UI线程。

有没有办法,如果请求listenerB,我可以阻止/中止/抢占listenerA的执行吗?

预计用户会希望看到他最新动作的回应。如果两个行为相似,则不应遵守先前的行动。

2 个答案:

答案 0 :(得分:0)

要了解Backbone如何处理路由,可以查看Backbone.History中的一些代码:

 if (this._hasPushState) {
        Backbone.$(window).on('popstate', this.checkUrl);
      } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
        Backbone.$(window).on('hashchange', this.checkUrl);
      } else if (this._wantsHashChange) {
        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
      }

如果您使用的是现代浏览器,则第二个如果黑色将订阅hashChange个活动,并且只要您在链接之间导航,它就会调用checkUrl来管理对相应操作的调用。

所以直接回答你的问题就是不,你不能。

但是你可以使用一些解决方法,具体取决于你在行动中做了什么。


第一个解决方案。

使用setTimeout()或类似的_.debounce()功能。选择所有需要保护或单一处理的链接,然后导航到所需的网址:

$(document.body).on('click', 'a:not([reference-to-out])', function(e){
   e.preventDefault();
   if (app.linkTimeoutId) {
      clearTimout(app.linkTimeoutId);
   } 

   app.linkTimeoutId = setTimeout(function () {
          app.linkTimeoutId = null;           
          app.router.navigate(e.currentTarget.pathname, {trigger: true});
   }, 500)

 });

第二个解决方案

如果您的繁重任务与网络相关(获取集合,向远程执行另一个请求),请跟踪它们保留在另一个对象中并在Backbone.Router触发&#39;路由时取消它们。事件。这样可以防止大量不必要的操作。

第三个解决方案

我在考虑$.Deferred个对象,但在这种情况下,你应该用它包装所有控制器的动作,并跟踪它们。

答案 1 :(得分:0)

您可以更改Backbone处理路由注册的方式,以在路由匹配和回调执行之间引入延迟。例如,

var Router = Backbone.Router.extend({
    routes: {
        ":id" : "go"
    },

    route: function(route, name, callback) {
        var router = this;
        if (!callback) callback = this[name];

        var f = function() {
            var args = _.toArray(arguments);
            console.log('Clicked route', args[0]);

            if (router.timer)
                clearTimeout(router.timer);

            router.timer = setTimeout(function() {
                callback.apply(router, args);
            }, 1000);

        };
        return Backbone.Router.prototype.route.call(router, route, name, f);
    },

    go: function(id) {
        console.log("Routed "+id);
    }
});


var r = new Router();
Backbone.history.start();

导航到路线将设置计时器。如果在给定的时间内发生了另一次导航,则取消定时器并中止操作。

请参阅http://jsfiddle.net/nikoshr/0ws8d0ky/了解演示