Skip to content

Commit 3108c55

Browse files
committed
Allow beforeSend to be asynchronous
1 parent 9181048 commit 3108c55

File tree

2 files changed

+131
-3
lines changed

2 files changed

+131
-3
lines changed

can-ajax-test.js

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,3 +611,117 @@ QUnit.test("beforeSend", function (assert) {
611611
done();
612612
});
613613
});
614+
615+
QUnit.test("abort", function (assert) {
616+
var done = assert.async();
617+
var restore = makeFixture(function () {
618+
var aborted = false;
619+
this.open = function (type, url) {};
620+
this.setRequestHeader = function (header, value) {};
621+
this.send = function () {};
622+
this.abort = function() {
623+
assert.ok(true, 'called the underlying XHR.abort');
624+
done();
625+
};
626+
});
627+
628+
var request = ajax({
629+
url: "/foo"
630+
});
631+
632+
request.abort();
633+
});
634+
635+
QUnit.test("abort prevents sending if beforeSend is not finished", function (assert) {
636+
var done = assert.async();
637+
var restore = makeFixture(function () {
638+
var aborted = false;
639+
this.open = function (type, url) {};
640+
this.setRequestHeader = function (header, value) {};
641+
this.abort = function() {
642+
assert.ok(true, 'XHR abort was called');
643+
};
644+
this.send = function () {
645+
assert.notOk(true, 'should not have been called');
646+
};
647+
});
648+
649+
var request = ajax({
650+
url: "/foo",
651+
beforeSend: function (xhr){
652+
return new Promise(resolve => {
653+
setTimeout(resolve, 1);
654+
});
655+
}
656+
});
657+
658+
request.abort();
659+
660+
setTimeout(done, 10);
661+
});
662+
663+
QUnit.module("beforeSend async", function(hooks) {
664+
var headers, restore;
665+
666+
hooks.beforeEach(function() {
667+
headers = {};
668+
restore = makeFixture(function () {
669+
this.open = function (type, url) {};
670+
671+
this.send = function () {
672+
this.readyState = 4;
673+
this.status = 204;
674+
this.responseText = '';
675+
this.onreadystatechange();
676+
};
677+
678+
this.setRequestHeader = function (header, value) {
679+
headers[header] = value;
680+
};
681+
});
682+
});
683+
684+
hooks.afterEach(function() {
685+
restore();
686+
});
687+
688+
QUnit.test("waits for promise to resolve", function (assert) {
689+
var done = assert.async();
690+
691+
ajax({
692+
url: "/foo",
693+
beforeSend: function (xhr){
694+
return new Promise(resolve => {
695+
setTimeout(() => {
696+
xhr.setRequestHeader("Authorization", "Bearer 123");
697+
resolve();
698+
}, 1);
699+
});
700+
}
701+
}).then(function (value) {
702+
assert.ok(headers.hasOwnProperty('Authorization'), "authorization header set");
703+
}, function (reason) {
704+
assert.notOk(reason, "request failed with reason = ", reason);
705+
}).then(done);
706+
});
707+
708+
QUnit.test("rejects the ajax promise on failure", function (assert) {
709+
var done = assert.async();
710+
var error = new Error();
711+
712+
ajax({
713+
url: "/foo",
714+
beforeSend: function (xhr){
715+
return new Promise((resolve, reject) => {
716+
setTimeout(() => {
717+
reject(error);
718+
}, 1);
719+
});
720+
}
721+
}).then(function (value) {
722+
assert.notOk(true, "request should have rejected");
723+
}, function (reason) {
724+
assert.ok(true, "request rejected");
725+
}).then(done);
726+
});
727+
});

can-ajax.js

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,10 @@ function ajax(o) {
137137
deferred.reject = reject;
138138
});
139139
var requestUrl;
140+
var isAborted = false;
140141

141142
promise.abort = function () {
143+
isAborted = true;
142144
xhr.abort();
143145
};
144146

@@ -250,11 +252,23 @@ function ajax(o) {
250252
}
251253
}
252254

253-
if(o.beforeSend){
254-
o.beforeSend.call( o, xhr, o );
255+
function send () {
256+
if(!isAborted) {
257+
xhr.send(data);
258+
}
255259
}
256260

257-
xhr.send(data);
261+
if(o.beforeSend){
262+
const result = o.beforeSend.call( o, xhr, o );
263+
if(result && typeof result.then === 'function') {
264+
result.then(send).catch(deferred.reject);
265+
} else {
266+
send();
267+
}
268+
} else {
269+
send();
270+
}
271+
258272
return promise;
259273
}
260274

0 commit comments

Comments
 (0)