fetch获取JSON赋值变量报不可迭代错误的解决方法
问题根因
这个报错和赋值操作本身无关,核心是fetch是异步非阻塞API:你发起fetch请求后,JS引擎不会等待接口返回,会直接执行后续用到advi变量的逻辑。此时接口还没响应,advi还是初始的undefined值,只要你对undefined做解构、循环遍历这类依赖迭代器的操作,就会抛出undefined is not iterable的错误。
你把回调换成.then(console.log)能正常输出,是因为console.log被放在Promise的回调链里,只有接口成功返回、JSON解析完成后才会执行,自然能拿到正确数据。
可行实现方案
不要用提前声明外部变量、等异步赋值后再使用的写法,这种写法时序不可控,非常容易出bug,推荐以下两种标准写法:
方案1:Promise 链式调用
把所有依赖接口返回值的业务逻辑,直接放到Promise的then回调链中执行,同时记得加错误捕获:
fetch("https://api.adviceslip.com/advice") .then(res => { if (!res.ok) throw new Error("接口请求异常") return res.json() }) .then(advData => { // 所有用到advice数据的逻辑全部写在这里 const adviceText = advData.slip.advice // 示例:将内容渲染到页面 document.getElementById("advice-content").textContent = adviceText }) .catch(err => console.error("请求失败:", err))
方案2:async/await 语法糖(更易维护)
如果觉得链式回调嵌套不好维护,可以用async/await写异步逻辑,写法和同步代码逻辑一致,注意必须包裹在async函数内:
async function loadAdvice() { try { const res = await fetch("https://api.adviceslip.com/advice") if (!res.ok) throw new Error("接口请求异常") const advData = await res.json() // 此处可以直接使用返回的advData写业务逻辑 const adviceText = advData.slip.advice document.getElementById("advice-content").textContent = adviceText // 如果其他逻辑需要用到这份数据,直接return即可 return advData } catch (err) { console.error("请求失败:", err) } } // 执行函数 loadAdvice()
注意事项
- 绝对不要在fetch异步回调的外部,直接读取你提前声明的
advi变量:在fetch语句后立刻操作advi,100%会拿到undefined,因为此时接口请求还没完成。 - 如果确实需要把数据存在全局/外层作用域复用,必须加加载状态判断,确认数据已经赋值完成后再执行对应逻辑,这种写法维护成本高,非必要不推荐。
内容的提问来源于stack exchange,提问作者supasiblings
相关产品推荐
相关产品推荐

