为何Fetch API赋值变量countries后打印为undefined?求解决方案
为什么你的countries变量打印出来是undefined?
嘿,我来帮你拆解下这个问题,顺便给你几个可行的解决方案~
问题原因
核心问题就是异步操作的执行时序,再加上代码里有个小语法错误:
异步任务的执行顺序
JavaScript是单线程的,像fetch这种网络请求属于异步任务,它不会阻塞主线程,而是会被放到任务队列里等待执行。你现在的代码里,countries变量是提前声明的,但赋值操作是在then回调里——这个回调要等fetch请求完成、数据解析好之后才会执行。如果在then回调之外(比如声明变量后直接打印)就去访问countries,这时候请求还没完成,赋值操作根本没执行,所以自然是undefined。代码里的小错误
你写的catch回调里,console.log(e...是不完整的,应该改成console.log(err),不然会触发语法错误,影响后续代码执行。
可行解决方案
方案一:在then回调内部处理数据(最直接)
既然then回调是确保数据已经拿到的地方,那所有需要用到countries的逻辑都放在这里就好:
async function getCountries(url) { const data = await fetch(url); const response = await data.json(); return response; } document.addEventListener('DOMContentLoaded', () => { getCountries('https://restcountries.eu/rest/v2/all') .then(res => { const countries = res; console.log(countries); // 这里打印肯定有值 // 所有依赖countries的操作都写在这里,比如渲染页面 }) .catch(err => console.log(err)); // 修正了catch里的错误 });
方案二:用async/await改写回调,让代码更清爽
既然你已经用了async函数,那干脆把DOMContentLoaded的回调也改成async的,这样就能用await替代then,代码逻辑更像同步写法:
async function getCountries(url) { const data = await fetch(url); const response = await data.json(); return response; } document.addEventListener('DOMContentLoaded', async () => { try { const countries = await getCountries('https://restcountries.eu/rest/v2/all'); console.log(countries); // 这里能拿到正确数据 // 后续直接用countries就行,不用嵌套回调 } catch (err) { console.log(err); } });
方案三:如果一定要在外部使用(不推荐,容易踩坑)
要是你非得在回调外部访问countries,可以通过自定义事件来通知数据已准备好,避免时序问题:
let countries; async function getCountries(url) { const data = await fetch(url); const response = await data.json(); return response; } document.addEventListener('DOMContentLoaded', () => { getCountries('https://restcountries.eu/rest/v2/all') .then(res => { countries = res; // 触发自定义事件,告诉外部数据准备好了 document.dispatchEvent(new CustomEvent('countriesLoaded')); }) .catch(err => console.log(err)); }); // 监听自定义事件,数据准备好后再操作 document.addEventListener('countriesLoaded', () => { console.log(countries); // 这里就能拿到值了 });
总结
异步操作的核心就是不能提前拿结果,必须等异步任务完成(要么用then回调,要么用await)之后,再去处理返回的数据。
内容的提问来源于stack exchange,提问作者RastaCode
相关产品推荐
相关产品推荐

