如何在另一个函数内调用异步函数并获取响应?API调用报错求助
问题分析与解决方案
首先,你的问题核心是没有正确处理fetch的异步特性,这也是前端新手常踩的坑,我来一步步帮你解决:
1. 为什么getCategory()返回undefined?
fetch是异步操作,它不会阻塞代码执行——当你调用getCategory()时,函数会立刻执行到fetch语句,然后直接返回(默认返回undefined),根本没等API请求完成、拿到数据。
要解决这个问题,你需要让getCategory()返回fetch生成的Promise,这样外部调用时就能通过.then()或async/await等待异步结果:
function getCategory() { // 关键:返回整个fetch Promise链 return fetch('https://api.chucknorris.io/jokes/categories') .then(res => { // 先检查响应是否成功(HTTP状态码200-299) if (!res.ok) { throw new Error(`请求失败,状态码:${res.status}`); } return res.json(); }) .then(data => { console.log(data); // 这里依然可以打印数据 return data; // 把数据返回给调用者 }) .catch(err => { console.error('获取分类出错:', err); throw err; // 抛出错误,让调用者可以处理 }); }
现在调用getCategory()时,就可以拿到有效的分类数据了:
// 示例:在DOM加载完成后获取分类 document.addEventListener('DOMContentLoaded', () => { getCategory().then(categories => { // 这里可以用categories做任何事,比如渲染到页面 console.log('拿到的分类列表:', categories); }).catch(err => { // 处理错误,比如提示用户 alert('获取分类失败,请检查网络'); }); });
2. 为什么generateRandomQuotes(e)会抛出JSON解析错误?
这个错误"Unexpected token u in JSON at position 0"几乎可以肯定是因为你尝试解析undefined("u"是undefined的首字母)。大概率是你在调用getCategory()时,直接用了它的返回值(也就是之前的undefined)去做JSON处理,或者请求随机笑话时的响应为空/无效。
我们同样用正确的异步方式改写generateRandomQuotes,并添加错误处理:
function generateRandomQuotes(selectedCategory) { return fetch(`https://api.chucknorris.io/jokes/random?category=${selectedCategory}`) .then(res => { if (!res.ok) { throw new Error(`请求笑话失败,状态码:${res.status}`); } return res.json(); }) .then(quoteData => { console.log(quoteData); return quoteData; }) .catch(err => { console.error('生成笑话出错:', err); throw err; }); }
然后在事件监听里正确调用:
document.addEventListener('DOMContentLoaded', () => { // 假设你有一个按钮触发生成笑话 const quoteBtn = document.getElementById('quoteBtn'); quoteBtn.addEventListener('click', (e) => { e.preventDefault(); // 先确保你已经拿到了选中的分类(这里示例用'animal',替换成实际选中值) const category = 'animal'; generateRandomQuotes(category).then(quote => { // 把笑话渲染到页面 document.getElementById('quoteDisplay').textContent = quote.value; }).catch(err => { document.getElementById('quoteDisplay').textContent = '获取笑话失败,请重试'; }); }); });
可选:用async/await让代码更直观
如果你觉得.then()链看起来繁琐,可以用async/await语法改写,逻辑更清晰:
async function getCategory() { try { const res = await fetch('https://api.chucknorris.io/jokes/categories'); if (!res.ok) { throw new Error(`请求失败,状态码:${res.status}`); } const data = await res.json(); console.log(data); return data; } catch (err) { console.error('获取分类出错:', err); throw err; } } async function generateRandomQuotes(selectedCategory) { try { const res = await fetch(`https://api.chucknorris.io/jokes/random?category=${selectedCategory}`); if (!res.ok) { throw new Error(`请求笑话失败,状态码:${res.status}`); } const quoteData = await res.json(); console.log(quoteData); return quoteData; } catch (err) { console.error('生成笑话出错:', err); throw err; } } // 调用示例(注意要在async函数里用await) document.addEventListener('DOMContentLoaded', async () => { try { const categories = await getCategory(); console.log('分类列表:', categories); } catch (err) { alert('获取分类失败'); } });
内容的提问来源于stack exchange,提问作者Arne
相关产品推荐
相关产品推荐

