/
githubmirror
/
axios
Обзор
Документация
Войти
/
githubmirror
/
axios
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v1.x
lib/core/InterceptorManager.js
155 строк
4 KB
Jay
fix(interceptors): trim trailing ejected handlers (#11087)
29 июл 2026, 20:39
Не верифицирован
29 июл 2026, 20:39
712e023
Код
Авторство
О чём код?
'use strict'; import utils from '../utils.js'; const $internals = Symbol('internals'); function trimHandlers(handlers) { while (handlers.length && handlers[handlers.length - 1] === null) { handlers.pop(); } } function syncHandlerEntries(manager, internals) { const handlers = manager.handlers; if (handlers !== internals.handlersRef) { internals.handlersRef = handlers; internals.handlerEntries.clear(); } else if (handlers.length !== internals.handlersLength) { if (!handlers.length) { internals.handlerEntries.clear(); } else { internals.handlerEntries.forEach(function removeStaleEntry(entry, id) { if (handlers[entry.index] !== entry.handler) { internals.handlerEntries.delete(id); } }); } } internals.handlersLength = handlers.length; } class InterceptorManager { constructor() { this.handlers = []; this[$internals] = { handlersRef: this.handlers, handlersLength: this.handlers.length, handlerEntries: new Map(), iterationDepth: 0, nextId: 0, }; } /** * Add a new interceptor to the stack * * @param {Function} fulfilled The function to handle `then` for a `Promise` * @param {Function} rejected The function to handle `reject` for a `Promise` * @param {Object} options The options for the interceptor, synchronous and runWhen * * @return {Number} An ID used to remove interceptor later */ use(fulfilled, rejected, options) { const handler = { fulfilled, rejected, synchronous: options ? options.synchronous : false, runWhen: options ? options.runWhen : null, }; const internals = this[$internals]; syncHandlerEntries(this, internals); const id = internals.nextId++; this.handlers.push(handler); internals.handlerEntries.set(id, { handler, index: this.handlers.length - 1, }); internals.handlersLength = this.handlers.length; return id; } /** * Remove an interceptor from the stack * * @param {Number} id The ID that was returned by `use` * * @returns {void} */ eject(id) { const internals = this[$internals]; syncHandlerEntries(this, internals); const entry = internals.handlerEntries.get(id); if (entry) { internals.handlerEntries.delete(id); // Ignore IDs invalidated by clear or direct replacement of handlers. if (this.handlers[entry.index] !== entry.handler) { return; } this.handlers[entry.index] = null; // Do not reuse an index while forEach is walking its length snapshot. if (!internals.iterationDepth) { trimHandlers(this.handlers); internals.handlersLength = this.handlers.length; } } } /** * Clear all interceptors from the stack * * @returns {void} */ clear() { if (this.handlers) { this.handlers = []; syncHandlerEntries(this, this[$internals]); } } /** * Iterate over all the registered interceptors * * This method is particularly useful for skipping over any * interceptors that may have become `null` calling `eject`. * * @param {Function} fn The function to call for each interceptor * * @returns {void} */ forEach(fn) { const internals = this[$internals]; syncHandlerEntries(this, internals); internals.iterationDepth++; try { utils.forEach(this.handlers, function forEachHandler(h) { if (h !== null) { fn(h); } }); } finally { if (!--internals.iterationDepth) { syncHandlerEntries(this, internals); trimHandlers(this.handlers); internals.handlersLength = this.handlers.length; } } } } export default InterceptorManager;