Fetch API封装函数返回数据undefined问题求助
解决Fetch封装函数返回undefined的问题
问题背景
封装了Fetch API的crudHandler函数,用于调用API获取当前登录用户信息供多视图使用。API调用已成功获取数据,但在视图中访问时返回undefined。
问题代码
主封装函数
function crudHandler(options: IFetchAPIOptions) { const url = options.url || ''; const contentType = options.contentType || ContentTypes["application/json"]; const failMessage = options.failMessage || ''; const successMessage = options.successMessage || ''; const mode = options.mode || 'cors'; const redirect = options.redirect || 'follow'; const body = options.body || null; const method = options.method || "GET"; const success = options.success || null const error = options.error || null let serverSideMessaging = options.serverSideMessaging || false; function errorHandler(statusCode: number, errorMessage: string): void { if (failMessage != null) { matchBookerAlert('danger', failMessage); serverSideMessaging = false; } if (serverSideMessaging == true) { matchBookerAlert('danger', statusCode + " - " + errorMessage); } } function messageHandler(data: IMessageHandler): void { if (successMessage.length > 0) { matchBookerAlert('success', successMessage); serverSideMessaging = false; } if (serverSideMessaging == true && 'SuccessMessage' in data) { matchBookerAlert('success', data.successMessage); } if (serverSideMessaging == true && 'FailMessage' in data) { matchBookerAlert('danger', data.failMessage); } } await fetch(url, { method: method, headers: { "content-type": contentType }, mode: mode as RequestMode, redirect: redirect as RequestRedirect, body: body, }) .then(response => { if (!response.ok) { if (error !== null) { error(); // need to know what to pass } errorHandler(response.status, response.statusText); } return response.json(); }) .then(data => { if (success !== null) { success(data); } messageHandler(data); }) .catch(error => { console.error(error); }); }
获取用户信息的辅助函数
function getCurrentUser(){ var data = crudHandler({ url: "/api/AccountApi/GetCurrentUserInfo", contentType: ContentTypes["application/json"], }); return data;// I know this is wrong but I don't know how to return the data. }
调用代码
var currentUser = getCurrentUser(); console.log(currentUser);
后端API方法
[HttpGet] [Authorize] [Route("GetCurrentUserInfo")] public ActionResult GetCurrentUserInfo() { var user = UserManager.FindByIdAsync(CurrentUserId).Result; if (user == null) return NotFound("User not found"); CurrentUserInfo currentUserInfo = new CurrentUserInfo() { FirstName = user.FirstName, LastName = user.Lastname, Email = user.Email, IsAdmin = IsAdmin, IsBooker = IsBooker, IsOwner = IsOwner, }; return Ok(currentUserInfo); }
问题原因
- 异步处理缺失:
crudHandler使用了await但未标记为async函数,也没有返回异步操作的结果(Promise),导致调用该函数直接得到undefined。 - 同步调用异步函数:
getCurrentUser直接同步调用crudHandler,没有等待异步操作完成,因此返回的不是API数据而是undefined。
修复方案
1. 修改crudHandler为异步函数并返回数据
将函数标记为async,使用try/catch处理异步错误,最终返回API响应数据:
async function crudHandler(options: IFetchAPIOptions): Promise<any> { const url = options.url || ''; const contentType = options.contentType || ContentTypes["application/json"]; const failMessage = options.failMessage || ''; const successMessage = options.successMessage || ''; const mode = options.mode || 'cors'; const redirect = options.redirect || 'follow'; const body = options.body || null; const method = options.method || "GET"; const success = options.success || null const error = options.error || null let serverSideMessaging = options.serverSideMessaging || false; function errorHandler(statusCode: number, errorMessage: string): void { if (failMessage != null) { matchBookerAlert('danger', failMessage); serverSideMessaging = false; } if (serverSideMessaging == true) { matchBookerAlert('danger', statusCode + " - " + errorMessage); } } function messageHandler(data: IMessageHandler): void { if (successMessage.length > 0) { matchBookerAlert('success', successMessage); serverSideMessaging = false; } if (serverSideMessaging == true && 'SuccessMessage' in data) { matchBookerAlert('success', data.successMessage); } if (serverSideMessaging == true && 'FailMessage' in data) { matchBookerAlert('danger', data.failMessage); } } try { const response = await fetch(url, { method: method, headers: { "content-type": contentType }, mode: mode as RequestMode, redirect: redirect as RequestRedirect, body: body, }); if (!response.ok) { error?.(response.status, response.statusText); // 传递错误信息给回调 errorHandler(response.status, response.statusText); throw new Error(`${response.status} - ${response.statusText}`); } const data = await response.json(); success?.(data); messageHandler(data); return data; // 返回API数据 } catch (err) { console.error(err); throw err; // 抛出错误让调用方处理 } }
2. 修改getCurrentUser为异步函数
使用await等待crudHandler的异步结果:
async function getCurrentUser(): Promise<any> { const data = await crudHandler({ url: "/api/AccountApi/GetCurrentUserInfo", contentType: ContentTypes["application/json"], }); return data; }
3. 正确调用获取用户信息
由于异步函数不能直接同步调用,需使用async/await或.then()处理结果:
// 方式1:在async函数中使用await async function loadUserInfo() { try { const currentUser = await getCurrentUser(); console.log(currentUser); // 在这里更新视图逻辑 } catch (err) { console.error('获取用户信息失败:', err); } } loadUserInfo(); // 方式2:使用.then()链式调用 getCurrentUser() .then(currentUser => { console.log(currentUser); // 更新视图逻辑 }) .catch(err => console.error('获取用户信息失败:', err));
额外优化点
- 为返回数据定义具体的TypeScript接口(比如
CurrentUserInfo),替代any类型,提升类型安全性。 - 错误回调传递具体的错误信息,方便调用方自定义错误处理逻辑。
内容的提问来源于stack exchange,提问作者Nick1991
相关产品推荐
相关产品推荐

