abortcontroller 可优雅中止扫码登录轮询:创建控制器传 signal 给 fetch 实现请求中断;用户取消时调用 abort() 终止轮询并清理 ui;页面卸载或隐藏时自动 abort 防内存泄漏;结合 promise.race 支持超时与手动取消双控制。

扫码登录过程中,用户可能中途取消操作,比如关闭弹窗、点击“取消”按钮或切换页面。用 AbortController 可以优雅地中止正在进行的轮询请求或长连接,避免无效请求堆积、内存泄漏或回调误执行。
创建 AbortController 并传入 fetch 请求
扫码登录通常依赖轮询(如每 2 秒请求一次 /login/status)来检查扫码和授权状态。在发起请求前创建控制器,并将 signal 传给 fetch:
const controller = new AbortController();
const { signal } = controller;
// 启动轮询
const pollLoginStatus = async () => {
try {
const res = await fetch('/api/login/status', { signal });
const data = await res.json();
if (data.status === 'success') {
console.log('登录成功', data.user);
return data;
}
setTimeout(pollLoginStatus, 2000); // 继续轮询
} catch (err) {
if (err.name === 'AbortError') {
console.log('轮询已取消');
return;
}
console.error('轮询出错', err);
}
};
pollLoginStatus();
用户点击取消时调用 abort()
当用户主动取消(如点击“关闭”按钮),只需调用 controller.abort(),所有监听该 signal 的 fetch 会立即抛出 AbortError,轮询自然终止:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
document.getElementById('cancel-btn').addEventListener('click', () => {
controller.abort(); // 中止所有关联请求
// 可选:清理 UI,如隐藏二维码弹窗
document.querySelector('.qrcode-modal').remove();
});
页面卸载前自动中止(防内存泄漏)
用户刷新或离开页面时,未清理的轮询可能继续运行。利用 beforeunload 或 visibilitychange 提前 abort:
// 页面隐藏或卸载时自动取消
window.addEventListener('beforeunload', () => controller.abort());
// 或更精准地监听页面可见性变化
document.addEventListener('visibilitychange', () => {
if (document.hidden) controller.abort();
});
配合 Promise.race 实现超时 + 取消双控制
扫码登录常需设置总超时(如 3 分钟),同时支持手动取消。可用 Promise.race 协同处理:
const timeout = (ms) => new Promise((_, reject) =>
setTimeout(() => reject(new Error('登录超时')), ms)
);
const loginPromise = Promise.race([
pollLoginStatus(), // 返回一个 Promise(需稍作封装)
timeout(180_000),
// 注意:signal 本身不直接返回 Promise,但 fetch 抛错可被 race 捕获
]);
loginPromise.catch(err => {
if (err.name === 'AbortError' || err.message === '登录超时') {
console.log(err.message);
}
});
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










