次の点を考慮してください。
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 ダック パンチの両方で、これはまさにそれが行うことです - しかし、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 Deferred チェーンを使用する必要があります。私はそれについて特に満足していませんが、何ができますか?