假设我的页面上有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的执行吗?
预计用户会希望看到他最新动作的回应。如果两个行为相似,则不应遵守先前的行动。
答案 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();
导航到路线将设置计时器。如果在给定的时间内发生了另一次导航,则取消定时器并中止操作。