JS中then函数无法为变量赋值的问题求助
问题分析与解决
你的问题核心是异步操作的执行顺序没搞清楚,fetch是异步的,它不会阻塞代码执行,所以你遇到了两个关键问题:
- 你在
client.on("ready")里调用bazar()后立刻打印d,这时候fetch还在请求数据,根本没来得及把data赋值给d,所以打印的还是初始值0。 bazar函数里的setTimeout放在了fetch的外面,不管请求成功失败,都会在1分钟后再次调用函数,可能导致多个请求同时跑,而且如果某次请求失败,d就不会更新。
修正后的代码
let d = 0; // 用let比var更安全,避免变量提升问题 async function bazar() { try { // 用async/await让异步代码看起来像同步,更易读 const response = await fetch('https://api.hypixel.net/skyblock/bazaar'); const data = await response.json(); d = data; console.debug('数据更新成功:', JSON.stringify(d)); // 每次更新后打印确认 } catch (error) { console.error('请求失败:', error); // 捕获错误,避免程序崩溃 } finally { // 不管请求成功失败,都调度下一次执行,确保每分钟跑一次 setTimeout(bazar, 60000); } } client.on("ready", () => { // 调用bazar后,不要立刻打印d,要等第一次请求完成 bazar().then(() => { console.debug('第一次初始化数据:', JSON.stringify(d)); }); });
关键改动说明
- 改用
async/await替代then链,异步逻辑更清晰,新手更容易理解执行顺序。 - 把
setTimeout放到finally里,确保不管请求成功还是失败,下一次调度都会执行,不会中断定时任务。 - 添加了
try/catch捕获请求过程中的错误(比如网络问题、API返回异常),避免程序因为一次请求失败就挂掉。 - 在
client.on("ready")里,通过bazar().then()来等待第一次请求完成后再打印d,这时候d已经被赋值了。 - 把
var换成let,var存在变量提升和全局污染问题,let是块级作用域,更符合现代JS规范。
另外,如果你不想用async/await,也可以用then链的方式修改,核心是把setTimeout放到then的末尾,并且在then里处理打印:
var d = 0; function bazar() { fetch('https://api.hypixel.net/skyblock/bazaar') .then(response => response.json()) .then(data => { d = data; console.debug('数据更新成功:', JSON.stringify(d)); // 请求成功后再调度下一次 setTimeout(bazar, 60000); }) .catch(error => { console.error('请求失败:', error); // 失败也继续调度下一次 setTimeout(bazar, 60000); }); } client.on("ready", () => { bazar(); // 如果要打印第一次的数据,得在bazar的then里加,或者用Promise包装 });
总之,记住异步操作不会立刻完成,所有依赖异步结果的代码都要放到回调(then)或者await之后。
内容的提问来源于stack exchange,提问作者Ren
相关产品推荐
相关产品推荐

