mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
fix(xhr): unsubscribe cancelToken and signal on error, timeout, and abort paths (#10787)
* test(xhr): add regression for cancelToken and signal listener cleanup on error paths * fix(xhr): unsubscribe cancelToken and signal on error, timeout, and abort paths --------- Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
@@ -108,6 +108,7 @@ export default isXHRAdapterSupported &&
|
|||||||
}
|
}
|
||||||
|
|
||||||
reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request));
|
reject(new AxiosError('Request aborted', AxiosError.ECONNABORTED, config, request));
|
||||||
|
done();
|
||||||
|
|
||||||
// Clean up request
|
// Clean up request
|
||||||
request = null;
|
request = null;
|
||||||
@@ -123,6 +124,7 @@ export default isXHRAdapterSupported &&
|
|||||||
// attach the underlying event for consumers who want details
|
// attach the underlying event for consumers who want details
|
||||||
err.event = event || null;
|
err.event = event || null;
|
||||||
reject(err);
|
reject(err);
|
||||||
|
done();
|
||||||
request = null;
|
request = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -143,6 +145,7 @@ export default isXHRAdapterSupported &&
|
|||||||
request
|
request
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
done();
|
||||||
|
|
||||||
// Clean up request
|
// Clean up request
|
||||||
request = null;
|
request = null;
|
||||||
@@ -192,6 +195,7 @@ export default isXHRAdapterSupported &&
|
|||||||
}
|
}
|
||||||
reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel);
|
reject(!cancel || cancel.type ? new CanceledError(null, config, request) : cancel);
|
||||||
request.abort();
|
request.abort();
|
||||||
|
done();
|
||||||
request = null;
|
request = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -170,4 +170,50 @@ describe('cancel (vitest browser)', () => {
|
|||||||
const error = await promise.catch((thrown) => thrown);
|
const error = await promise.catch((thrown) => thrown);
|
||||||
expect(axios.isCancel(error)).toBe(true);
|
expect(axios.isCancel(error)).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('listener cleanup on error paths', () => {
|
||||||
|
for (const { label, trigger } of [
|
||||||
|
{ label: 'network error', trigger: (r) => r.onerror(new Error('Network Error')) },
|
||||||
|
{ label: 'timeout', trigger: (r) => r.ontimeout() },
|
||||||
|
{ label: 'browser abort', trigger: (r) => r.onabort() },
|
||||||
|
]) {
|
||||||
|
it(`unsubscribes cancelToken listener after ${label}`, async () => {
|
||||||
|
const source = axios.CancelToken.source();
|
||||||
|
const promise = axios
|
||||||
|
.get('/foo/bar', { cancelToken: source.token })
|
||||||
|
.catch((thrown) => thrown);
|
||||||
|
|
||||||
|
const request = await waitForRequest();
|
||||||
|
trigger(request);
|
||||||
|
await promise;
|
||||||
|
|
||||||
|
expect(source.token._listeners || []).toEqual([]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
it('removes AbortSignal listener after network error', async () => {
|
||||||
|
const controller = new AbortController();
|
||||||
|
let listenerCount = 0;
|
||||||
|
const nativeAdd = controller.signal.addEventListener.bind(controller.signal);
|
||||||
|
const nativeRemove = controller.signal.removeEventListener.bind(controller.signal);
|
||||||
|
controller.signal.addEventListener = (type, fn, options) => {
|
||||||
|
if (type === 'abort') listenerCount++;
|
||||||
|
return nativeAdd(type, fn, options);
|
||||||
|
};
|
||||||
|
controller.signal.removeEventListener = (type, fn, options) => {
|
||||||
|
if (type === 'abort') listenerCount--;
|
||||||
|
return nativeRemove(type, fn, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
const promise = axios
|
||||||
|
.get('/foo/bar', { signal: controller.signal })
|
||||||
|
.catch((thrown) => thrown);
|
||||||
|
|
||||||
|
const request = await waitForRequest();
|
||||||
|
request.onerror(new Error('Network Error'));
|
||||||
|
await promise;
|
||||||
|
|
||||||
|
expect(listenerCount).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user