如何为所有请求(提交、页面刷新等)添加全局参数windowID
给所有请求附加windowID的实现方案
嘿,这个需求我之前在项目里落地过,刚好能给你一套完整的解决思路,分几个部分来实现,确保所有请求都带上windowID:
第一步:生成并持久化windowID
首先得给每个标签页生成唯一的windowID,而且要保证页面刷新后不会变,标签页之间互不干扰。用sessionStorage存储最合适,因为它是标签页级别的,关闭标签就清除,完美符合需求:
// 页面加载时生成或获取windowID function getWindowID() { let windowID = sessionStorage.getItem('windowID'); if (!windowID) { // 生成唯一ID,这里用简化版UUID,也可以用更复杂的生成逻辑 windowID = 'win_' + Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15); sessionStorage.setItem('windowID', windowID); } return windowID; } // 初始化全局windowID const windowID = getWindowID();
第二步:拦截所有AJAX请求
方案1:拦截原生XMLHttpRequest
如果你的项目用原生XHR,我们可以重写它的open方法,在发送请求前自动拼接windowID参数:
// 保存原生的open方法 const originalXHROpen = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, password) { // 给URL添加windowID参数 const modifiedUrl = addParamToUrl(url, 'windowID', windowID); // 调用原生open方法 originalXHROpen.call(this, method, modifiedUrl, async, user, password); }; // 工具函数:给URL追加查询参数 function addParamToUrl(url, key, value) { const urlObj = new URL(url, window.location.origin); urlObj.searchParams.set(key, value); return urlObj.toString(); }
方案2:拦截fetch请求
现在很多项目用fetch,同样可以封装原生fetch方法,自动带上参数:
// 保存原生fetch const originalFetch = window.fetch; window.fetch = function(resource, options = {}) { let modifiedResource = resource; // GET请求直接在URL加参数 if (typeof resource === 'string' && (!options.method || options.method.toUpperCase() === 'GET')) { modifiedResource = addParamToUrl(resource, 'windowID', windowID); } // POST等带body的请求,根据body类型添加参数 else if (options.body) { if (typeof options.body === 'string') { try { const bodyObj = JSON.parse(options.body); bodyObj.windowID = windowID; options.body = JSON.stringify(bodyObj); } catch (e) { // 非JSON格式(比如form-data),直接追加字段 if (options.body instanceof FormData) { options.body.append('windowID', windowID); } } } else if (options.body instanceof FormData) { options.body.append('windowID', windowID); } } // 调用原生fetch return originalFetch(modifiedResource, options); };
方案3:Axios等HTTP库的拦截方式
如果你的项目用Axios,直接用请求拦截器就能搞定,更简洁:
axios.interceptors.request.use(config => { // GET请求加URL参数 if (config.method === 'get') { config.params = { ...config.params, windowID }; } // POST等请求加在请求体里 else { if (typeof config.data === 'object') { config.data = { ...config.data, windowID }; } else if (config.data instanceof FormData) { config.data.append('windowID', windowID); } } return config; });
第三步:处理表单提交
不管是GET还是POST表单,都要给它们自动加上windowID隐藏字段,监听全局表单提交事件即可:
document.addEventListener('submit', function(e) { const form = e.target; // 避免重复添加字段 let windowIDInput = form.querySelector('input[name="windowID"]'); if (!windowIDInput) { windowIDInput = document.createElement('input'); windowIDInput.type = 'hidden'; windowIDInput.name = 'windowID'; windowIDInput.value = windowID; form.appendChild(windowIDInput); } else { windowIDInput.value = windowID; } });
第四步:处理页面刷新的请求
页面刷新时浏览器会直接请求当前页面URL,这里给两种处理方式:
方式1:修改URL参数(适合GET页面)
页面加载时检查URL是否带windowID,没有的话就用replaceState修改URL(不会触发刷新),或者强制重定向(服务器需要在页面请求时拿到参数):
window.addEventListener('load', function() { const urlObj = new URL(window.location.href); if (!urlObj.searchParams.has('windowID')) { urlObj.searchParams.set('windowID', windowID); // 仅修改URL,不触发页面刷新 window.history.replaceState({}, document.title, urlObj.toString()); // 如果服务器需要在页面请求时就拿到参数,取消下面注释(会触发二次加载) // window.location.replace(urlObj.toString()); } });
方式2:通过Cookie传递
不想修改URL的话,可以把windowID存在Cookie里,浏览器刷新时会自动携带Cookie,服务器直接从Cookie读取即可:
// 将windowID存入Cookie,有效期同会话 document.cookie = `windowID=${windowID}; path=/; same-site=lax`;
内容的提问来源于stack exchange,提问作者Davide
相关产品推荐
相关产品推荐

