异步fetch函数返回undefined问题:不修改函数内部的解决方法
异步fetch函数返回undefined的处理方案
问题背景
你有一个意图等待2秒后返回对象的异步fetch函数:
async function fetch() { var object; await setTimeout(() => { object = { name: 'User', data: 'API Data' } }, 2000); return object; }
调用时希望2秒后显示对象,但执行以下代码时,会同时打印DONE!和错误Cannot read properties of undefined (reading 'name'):
fetch().then((val) => { console.log("DONE!"); console.log(val.name); }).catch((err) => { console.log("ERROR!"); console.log(err); });
尝试用Promise封装调用也未成功:
let promise = new Promise((resolve, reject) => { let request = fetch(); if (request !== undefined) resolve(request); else reject(request); }).then((val) => { console.log(val); });
需求:不修改fetch函数内部代码(可删除函数内的async和await,但不能添加Promise等内部逻辑),如何正确判断fetch()已返回有效值再进行打印?
核心问题
原fetch函数中的await setTimeout无效,因为setTimeout不返回Promise,await会直接跳过它,导致函数立即返回undefined;2秒后object才会被赋值,但此时函数已经执行完毕返回了。
解决方案
方案1:删除fetch的async/await,外部轮询检查结果
首先修改fetch函数(仅删除async和await):
function fetch() { var object; setTimeout(() => { object = { name: 'User', data: 'API Data' } }, 2000); return object; }
然后在外部通过Promise封装轮询逻辑,等待fetch()返回有效值:
function waitForValidResult() { return new Promise((resolve, reject) => { // 超时逻辑,避免无限等待 const timeoutId = setTimeout(() => { reject(new Error("等待结果超时")); }, 5000); const checkResult = () => { const result = fetch(); if (result !== undefined) { clearTimeout(timeoutId); resolve(result); } else { setTimeout(checkResult, 100); // 每100ms检查一次 } }; checkResult(); }); } // 调用示例 waitForValidResult() .then((val) => { console.log("DONE!"); console.log(val.name); // 输出:User }) .catch((err) => { console.log("ERROR!"); console.log(err.message); });
方案2:将fetch的object改为全局变量,监听全局变量
如果允许修改fetch中object的作用域(改为全局),可以直接监听这个全局变量:
// 修改fetch:删除async/await,将object改为全局变量 let globalObject; function fetch() { setTimeout(() => { globalObject = { name: 'User', data: 'API Data' } }, 2000); return globalObject; } function waitForGlobalObject() { return new Promise((resolve, reject) => { const timeoutId = setTimeout(() => { reject(new Error("等待结果超时")); }, 5000); const check = () => { if (globalObject !== undefined) { clearTimeout(timeoutId); resolve(globalObject); } else { setTimeout(check, 100); } }; check(); }); } // 调用示例 waitForGlobalObject() .then((val) => { console.log("DONE!"); console.log(val.name); }) .catch((err) => { console.log("ERROR!"); console.log(err.message); });
内容的提问来源于stack exchange,提问作者Lepy
相关产品推荐
相关产品推荐

