Javascript .back,and.pushState-两部历史的故事
这不是一个问题,而是一个有趣问题的发现。这也是一种“从失败中学习” 我正在尝试为IE的HTML5历史记录编写单元测试(使用window.hash替代状态维护)。duckpunch按预期工作,在用户测试期间,我在IE、Chrome和Firefox中得到了一致的结果Javascript .back,and.pushState-两部历史的故事,javascript,html,history,Javascript,Html,History,这不是一个问题,而是一个有趣问题的发现。这也是一种“从失败中学习” 我正在尝试为IE的HTML5历史记录编写单元测试(使用window.hash替代状态维护)。duckpunch按预期工作,在用户测试期间,我在IE、Chrome和Firefox中得到了一致的结果 问题出在单元测试上。在它们中,我对history.pushState()、.replaceState、.back()和.forward()进行了各种组合。这些在Firefox和IE中运行良好,但Chrome给了我完全不一致的结果。下面的
问题出在单元测试上。在它们中,我对history.pushState()、.replaceState、.back()和.forward()进行了各种组合。这些在Firefox和IE中运行良好,但Chrome给了我完全不一致的结果。下面的答案解释了原因。考虑以下几点:
var originalPath = window.location.pathname.toString();
history.pushState({ value: 'Foo' }, '', 'state-1');
history.pushState({ value: 'Bar' }, '', 'state-2');
history.pushState({ value: 'Baz' }, '', 'state-3');
history.back();
history.back();
console.log(history.state.value);
//So we can hit refresh and see the results again...
setTimeout(function () {
history.replaceState(null, '', originalPath);
}, 250);
有人会期望这段代码返回“Foo”——在Firefox和我的IE duck punch中,这正是它所做的——但在Chrome中,它的响应是“Baz”
经过一些调查,我解决了这个问题:IE和Firefox同步更新历史记录,如果需要加载任何页面,那么就进行异步更新。Chrome似乎立即变得异步
证据:
window.onpopstate = function () {
console.log('ping');
}
history.pushState({ value: 'Foo' }, '', 'state-1');
history.back();
console.log('pong');
在Firefox中,它返回“ping”pong'-表示事件作为history.back()调用的一部分被调度。在Chrome中,它返回“pong”ping’-表示事件被放置在队列中进行调度
如果不使用此事件分派模型来管理历史记录和位置对象的状态,这将不会太糟糕,但显然是这样
window.onpopstate = function () {
console.log('Event...', history.state, window.location.pathname.toString());
}
history.pushState({ value: 'Foo' }, '', 'state-1');
history.back();
console.log('Inline...', history.state, window.location.pathname.toString());
这是一个有趣的怪癖,需要使用jQuery延迟链来正确处理我的单元测试。我对此并不特别高兴,但你能做些什么呢 为了在单元测试中处理异步返回事件,我使用和。这是一个更新历史事件中的计数器以跟踪chrome何时处理事件以及Jasmine的异步支持以阻止单元测试的案例,直到我们看到事件更改: 递增计数器:
History.Adapter.bind(window, 'statechange', function() {
// Increment the counter
window.historyEventCounter++;
});
Jasmine异步单元测试。等待将被阻止,直到历史事件发生:
describe('back navigation', function () {
it('should change url', function () {
var initialHistoryEventCount;
// Cache the initial count
runs(function() {
initialHistoryEventCount = window.historyEventCounter;
History.back();
});
// Block until the event counter changes
waitsFor(function() {
return (initialHistoryEventCount !== app.historyEventCounter);
}, "The page should be navigated back", 1000);
// Now confirm the expected back behaviour. Event failures will time-out.
runs(function() {
expect(window.location.href).toEqual("http:// my back url");
// ... more tests about the page state
});
}
}