JavaScript:Promise立即返回未等待异步流程完成的问题
解决异步调用getToken()无法立即返回bearer token的问题
我之前也踩过这个异步的坑!当你直接调用getToken()试图同步拿到bearer + token时,异步操作的本质就是不会阻塞代码等待API响应,所以你大概率拿到的是个未完成的Promise或者undefined,根本不是你想要的token值。
后来查了相关资料后,核心解决思路就是用Promise封装异步请求逻辑,同时加上超时处理,避免因为服务器响应慢或者网络问题导致代码一直处于等待状态。下面是具体的实现方案:
1. 把getToken()改造成返回Promise的函数
首先,我们需要让getToken()返回一个Promise对象,这样就能通过.then()或者async/await来获取异步返回的token:
function getToken() { return new Promise((resolve, reject) => { // 这里替换成你实际的API请求逻辑,比如用axios或者fetch fetch('/api/token') .then(response => { if (!response.ok) { throw new Error(`请求失败,状态码: ${response.status}`); } return response.json(); }) .then(data => { // 拼接成bearer格式的token const bearerToken = `bearer ${data.token}`; resolve(bearerToken); // 成功时返回token }) .catch(error => { reject(new Error(`获取token失败: ${error.message}`)); // 失败时抛出错误 }); }); }
2. 给请求加上超时保护
为了避免因为服务器处理缓慢或者网络异常导致代码无限等待,我们可以给Promise加上超时逻辑:
function getTokenWithTimeout(timeoutMs = 5000) { return new Promise((resolve, reject) => { // 设置超时定时器,默认5秒后触发 const timeoutTimer = setTimeout(() => { reject(new Error(`获取token超时,已超过${timeoutMs}毫秒`)); }, timeoutMs); // 发起API请求 fetch('/api/token') .then(response => { clearTimeout(timeoutTimer); // 请求成功,清除超时定时器 if (!response.ok) throw new Error(`HTTP错误: ${response.status}`); return response.json(); }) .then(data => { const bearerToken = `bearer ${data.token}`; resolve(bearerToken); }) .catch(error => { clearTimeout(timeoutTimer); // 请求失败,同样清除定时器 reject(error); }); }); }
3. 正确调用异步函数
现在你可以通过两种方式获取token:
方式一:用async/await(更直观,像同步代码一样)
async function fetchProtectedData() { try { const token = await getTokenWithTimeout(); console.log('成功拿到bearer token:', token); // 这里就可以用token请求需要授权的接口了 const response = await fetch('/api/protected-data', { headers: { 'Authorization': token } }); const data = await response.json(); console.log('受保护的数据:', data); } catch (error) { console.error('处理过程出错:', error.message); // 这里可以添加错误处理逻辑,比如提示用户重新登录 } } // 调用函数 fetchProtectedData();
方式二:用.then()链式调用
如果你不习惯async/await,也可以用传统的Promise链式调用:
getTokenWithTimeout() .then(token => { console.log('成功拿到bearer token:', token); return fetch('/api/protected-data', { headers: { 'Authorization': token } }); }) .then(response => response.json()) .then(data => console.log('受保护的数据:', data)) .catch(error => console.error('处理过程出错:', error.message));
关键知识点回顾
- 异步操作的结果不能直接同步返回,必须通过Promise的回调或者
async/await来获取 - 给异步请求加上超时,是为了保证代码的健壮性,避免无限等待
- 始终要处理Promise的
reject状态(也就是错误情况),不然会出现未捕获的Promise错误
内容的提问来源于stack exchange,提问作者Owen Carter
相关产品推荐
相关产品推荐

