Skip to content

Commit d92a0dd

Browse files
JiaLiPassionmhevery
authored andcommitted
fix(zone.js): should invoke xhr send task when no response error occurs (#38836)
Close #38795 in the XMLHttpRequest patch, when get `readystatechange` event, zone.js try to invoke `load` event listener first, then call `invokeTask` to finish the `XMLHttpRequest::send` macroTask, but if the request failed because the server can not be reached, the `load` event listener will not be invoked, so the `invokeTask` of the `XMLHttpRequest::send` will not be triggered either, so we will have a non finished macroTask there which will make the Zone not stable, also memory leak. So in this PR, if the `XMLHttpRequest.status = 0` when we get the `readystatechange` event, that means something wents wrong before we reached the server, we need to invoke the task to finish the macroTask. PR Close #38836
1 parent 5548571 commit d92a0dd

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

packages/zone.js/lib/browser/browser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,8 +149,12 @@ Zone.__load_patch('XHR', (global: any, Zone: ZoneType) => {
149149
// check whether the xhr has registered onload listener
150150
// if that is the case, the task should invoke after all
151151
// onload listeners finish.
152+
// Also if the request failed without response (status = 0), the load event handler
153+
// will not be triggered, in that case, we should also invoke the placeholder callback
154+
// to close the XMLHttpRequest::send macroTask.
155+
// https://github.com/angular/angular/issues/38795
152156
const loadTasks = target[Zone.__symbol__('loadfalse')];
153-
if (loadTasks && loadTasks.length > 0) {
157+
if (target.status !== 0 && loadTasks && loadTasks.length > 0) {
154158
const oriInvoke = task.invoke;
155159
task.invoke = function() {
156160
// need to load the tasks again, because in other

packages/zone.js/test/browser/XMLHttpRequest.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,30 @@ describe('XMLHttpRequest', function() {
268268
});
269269
});
270270

271+
it('should close xhr request if error happened when connect', function(done) {
272+
const logs: boolean[] = [];
273+
Zone.current
274+
.fork({
275+
name: 'xhr',
276+
onHasTask:
277+
(delegate: ZoneDelegate, curr: Zone, target: Zone, taskState: HasTaskState) => {
278+
if (taskState.change === 'macroTask') {
279+
logs.push(taskState.macroTask);
280+
}
281+
return delegate.hasTask(target, taskState);
282+
}
283+
})
284+
.run(function() {
285+
const req = new XMLHttpRequest();
286+
req.open('get', 'http://notexists.url', true);
287+
req.send();
288+
req.addEventListener('error', () => {
289+
expect(logs).toEqual([true, false]);
290+
done();
291+
});
292+
});
293+
});
294+
271295
it('should trigger readystatechange if xhr request trigger cors error', (done) => {
272296
const req = new XMLHttpRequest();
273297
let err: any = null;

0 commit comments

Comments
 (0)