如何在AutoLogout类中调用api.js的onResponse函数并正确使用回调
Alright, let's break down your problem and work through a couple of solid solutions that won't disrupt your existing codebase. The core issue here is accessing the x-expires-at header from API responses to reset your auto-logout timer, without altering how api is exported (since it's used everywhere) and without directly calling onResponse() from your AutoLogout class.
Option 1: Add a Lightweight Event System to the API Object
Since your api is exported as a function, we can attach simple event subscription/emission methods directly to this function object (functions are objects in JS, after all!). This lets your AutoLogout class listen for response events and act on the x-expires-at value.
Step 1: Update api.js to include event handling
// api.js function onResponse(response) { // Your existing onResponse logic here... // Extract x-expires-at and emit an event if it exists const expiresAt = response.headers.get('x-expires-at'); if (expiresAt && api.emit) { api.emit('token-expiry-update', expiresAt); } } // Your existing api() function definition const api = function(apiOptions) { // Existing API request logic that eventually calls onResponse() }; // Add simple event system methods to the api function api._eventListeners = {}; api.on = function(eventName, callback) { if (!this._eventListeners[eventName]) { this._eventListeners[eventName] = []; } this._eventListeners[eventName].push(callback); }; api.emit = function(eventName, data) { if (this._eventListeners[eventName]) { this._eventListeners[eventName].forEach(callback => callback(data)); } }; export default api;
Step 2: Subscribe to the Event in AutoLogout
// auto-logout.js import api from './api.js'; class AutoLogout { constructor() { // Subscribe to the token expiry update event api.on('token-expiry-update', (expiresAt) => { this.resetTokenExpiry(expiresAt); }); // Your existing AutoLogout initialization logic here... } resetTokenExpiry(expiresAt) { // Convert expiresAt to a timestamp and reset your auto-logout timer const expiryTimestamp = new Date(expiresAt).getTime(); const timeUntilExpiry = expiryTimestamp - Date.now(); // Update your timer logic here (e.g., clear existing timeout, set new one) this.clearAutoLogoutTimer(); this.setAutoLogoutTimer(timeUntilExpiry); } // Your existing AutoLogout methods (clearAutoLogoutTimer, setAutoLogoutTimer, etc.)... }
Option 2: Use Response Hooks for a Minimalist Approach
If you don't want to implement a full event system, you can add a hook system to api.js that lets you register callbacks to run when a response with x-expires-at is received.
Step 1: Add Hook Support to api.js
// api.js const responseExpiryHooks = []; function onResponse(response) { // Your existing onResponse logic here... const expiresAt = response.headers.get('x-expires-at'); if (expiresAt) { // Run all registered hooks with the expiresAt value responseExpiryHooks.forEach(hook => hook(expiresAt)); } } const api = function(apiOptions) { // Existing API request logic... }; // Method to register hooks api.registerExpiryHook = function(hook) { responseExpiryHooks.push(hook); }; // Optional: Method to unregister hooks (useful if your AutoLogout is destroyed) api.unregisterExpiryHook = function(hook) { const index = responseExpiryHooks.indexOf(hook); if (index !== -1) { responseExpiryHooks.splice(index, 1); } }; export default api;
Step 2: Register the Hook in AutoLogout
// auto-logout.js import api from './api.js'; class AutoLogout { constructor() { // Bind the hook method to preserve `this` context this.handleExpiryUpdate = this.resetTokenExpiry.bind(this); api.registerExpiryHook(this.handleExpiryUpdate); // Existing initialization logic... } resetTokenExpiry(expiresAt) { // Same logic as Option 1: update your auto-logout timer const expiryTimestamp = new Date(expiresAt).getTime(); const timeUntilExpiry = expiryTimestamp - Date.now(); this.clearAutoLogoutTimer(); this.setAutoLogoutTimer(timeUntilExpiry); } // If your component/class is destroyed, clean up the hook to prevent memory leaks destroy() { api.unregisterExpiryHook(this.handleExpiryUpdate); this.clearAutoLogoutTimer(); } // Existing methods... }
Key Benefits of These Approaches
- No breaking changes: Your existing
api()calls remain exactly the same—we're just adding methods to the existingapifunction object. - Loose coupling:
AutoLogoutdoesn't need direct access toonResponse(); it reacts to events/hooks triggered by the API layer. - Scalability: You can add other components that listen for the same expiry event if needed later.
Things to Watch For
- Ensure
x-expires-atis a valid date string (add error handling if your API might return invalid values). - If you instantiate
AutoLogoutmultiple times, make sure to unregister hooks in thedestroymethod (Option 2) to avoid duplicate callbacks.
内容的提问来源于stack exchange,提问作者Valay

