Abort previous pending XHR when navigating

This commit is contained in:
Robin North
2018-01-23 15:09:57 +00:00
parent 6000ad5620
commit 486ef0e0ba
8 changed files with 89 additions and 6 deletions

View File

@@ -10,7 +10,7 @@
<div class='body'> <div class='body'>
<h1>Index</h1> <h1>Index</h1>
Hello. Hello.
Go to <a href='page2.html' class="js-Pjax">Page 2</a> and view your console to see Pjax events. Go to <a href='page2.html' class="js-Pjax">Page 2</a> or <a href='page3.html' class="js-Pjax">Page 3</a> and view your console to see Pjax events.
Clicking on <a href='index.html'>this page</a> will just reload the page entirely. Clicking on <a href='index.html'>this page</a> will just reload the page entirely.
</div> </div>
</body> </body>

15
example/page3.html Normal file
View File

@@ -0,0 +1,15 @@
<!doctype html>
<html>
<head>
<meta charset='utf-8'>
<title>Hello</title>
<script src='../pjax.js'></script>
<script src='example.js'></script>
</head>
<body>
<div class='body'>
<h1>Page 3</h1>
Hello. Go to <a href='index.html' class="js-Pjax">Index</a>.
</div>
</body>
</html>

View File

@@ -145,16 +145,21 @@ Pjax.prototype = {
// } // }
}, },
doRequest: require("./lib/request.js"), abortRequest: require("./lib/abort-request.js"),
doRequest: require("./lib/send-request.js"),
loadUrl: function(href, options) { loadUrl: function(href, options) {
this.log("load href", href, options) this.log("load href", href, options)
// Abort any previous request
this.abortRequest(this.request)
trigger(document, "pjax:send", options); trigger(document, "pjax:send", options);
// Do the request // Do the request
options.requestOptions.timeout = this.options.timeout options.requestOptions.timeout = this.options.timeout
this.doRequest(href, options.requestOptions, function(html, request) { this.request = this.doRequest(href, options.requestOptions, function(html, request) {
// Fail if unable to load HTML via AJAX // Fail if unable to load HTML via AJAX
if (html === false) { if (html === false) {
trigger(document,"pjax:complete pjax:error", options) trigger(document,"pjax:complete pjax:error", options)

8
lib/abort-request.js Normal file
View File

@@ -0,0 +1,8 @@
var noop = require("./util/noop")
module.exports = function(request) {
if (request && request.readyState < 4) {
request.onreadystatechange = noop
request.abort()
}
}

1
lib/util/noop Normal file
View File

@@ -0,0 +1 @@
module.exports = function() {}

View File

@@ -0,0 +1,54 @@
var tape = require("tape")
var abortRequest = require("../../lib/abort-request.js")
var sendRequest = require("../../lib/send-request.js")
// Polyfill responseURL property into XMLHttpRequest if it doesn't exist,
// just for the purposes of this test
// This polyfill is not complete; it won't show the updated location if a
// redirection occurred, but it's fine for our purposes.
if (!("responseURL" in XMLHttpRequest.prototype)) {
var nativeOpen = XMLHttpRequest.prototype.open
XMLHttpRequest.prototype.open = function(method, url) {
this.responseURL = url
return nativeOpen.apply(this, arguments)
}
}
tape("test aborting xhr request", function(t) {
var requestCacheBust = sendRequest.bind({
options: {
cacheBust: true,
},
})
t.test("- pending request is aborted", function(t) {
var r = requestCacheBust("https://httpbin.org/delay/10", {}, function() {})
t.equal(r.readyState, 1, "xhr readyState is '1' (SENT)")
abortRequest(r)
t.equal(r.readyState, 0, "xhr readyState is '0' (ABORTED)")
t.equal(r.status, 0, "xhr HTTP status is '0' (ABORTED)")
t.equal(r.responseText, "", "xhr response is empty")
t.end()
})
t.test("- request is not aborted if it has already completed", function(t) {
var r = requestCacheBust("https://httpbin.org/get", {}, function() {
abortRequest(r)
t.equal(r.readyState, 4, "xhr readyState is '4' (DONE)")
t.equal(r.status, 200, "xhr HTTP status is '200' (OK)")
t.end()
})
})
t.test("- request is not aborted if it is undefined", function(t) {
var r
try {
abortRequest(r)
}
catch (e) {
t.fail("aborting an undefined request threw an error")
}
t.equal(typeof r, "undefined", "undefined xhr was ignored")
t.end()
})
t.end()
})

View File

@@ -1,6 +1,6 @@
var tape = require("tape") var tape = require("tape")
var request = require("../../lib/request.js") var sendRequest = require("../../lib/send-request.js")
// Polyfill responseURL property into XMLHttpRequest if it doesn't exist, // Polyfill responseURL property into XMLHttpRequest if it doesn't exist,
// just for the purposes of this test // just for the purposes of this test
@@ -18,7 +18,7 @@ tape("test xhr request", function(t) {
var url = "https://httpbin.org/get" var url = "https://httpbin.org/get"
t.test("- request is made, gets a result, and is cache-busted", function(t) { t.test("- request is made, gets a result, and is cache-busted", function(t) {
var requestCacheBust = request.bind({ var requestCacheBust = sendRequest.bind({
options: { options: {
cacheBust: true, cacheBust: true,
}, },
@@ -36,7 +36,7 @@ tape("test xhr request", function(t) {
}) })
}) })
t.test("- request is not cache-busted when configured not to be", function(t) { t.test("- request is not cache-busted when configured not to be", function(t) {
var requestNoCacheBust = request.bind({ var requestNoCacheBust = sendRequest.bind({
options: { options: {
cacheBust: false, cacheBust: false,
}, },