OpenWeatherMap API集成报错:Uncaught (in promise) TypeError: locations is not iterable
解决OpenWeatherMap Geo API集成时的"locations is not iterable"错误
错误根源
你遇到的TypeError: locations is not iterable,本质是OpenWeatherMap的地理编码API返回的数据不是你预期的数组:
- 当搜索词匹配到有效地点时,API返回地点数组;
- 当搜索词无匹配、请求参数格式错误时,API会返回包含错误信息的对象(示例:
{"cod":"404","message":"city not found"}),此时你尝试遍历这个对象就会触发错误。
修复步骤
1. 先确认API返回的数据结构
在api.js的fetchData中添加临时日志,查看实际返回内容:
export const fetchData = function (URL, callback) { fetch(`${URL}&appid=${api_key}`) .then((res) => res.json()) .then((data) => { console.log('API返回数据:', data); // 新增日志 callback(data); }); };
搜索一个不存在的地点,就能看到错误格式的返回结果。
2. 修改fetchData处理响应错误
OpenWeatherMap API会通过HTTP状态码和返回体的cod字段标识错误,在fetchData中提前处理这些情况:
export const fetchData = function (URL, callback) { fetch(`${URL}&appid=${api_key}`) .then((res) => { if (!res.ok) throw new Error(`请求失败: ${res.status}`); return res.json(); }) .then((data) => { // 检查是否为API返回的错误对象 if (data.cod && data.cod !== 200) { throw new Error(data.message || '未知API错误'); } callback(data); }) .catch((err) => { console.error('数据获取失败:', err); callback([]); // 回调传入空数组,避免后续遍历报错 }); };
3. 在app.js的回调中增加类型判断
即使fetchData处理了错误,也建议在回调里先确认locations是数组再执行遍历操作:
fetchData(url.geo(searchField.value), function (locations) { // 先判断是否为数组 if (!Array.isArray(locations)) { searchResult.innerHTML = '<p class="error">未找到匹配地点</p>'; searchField.classList.remove("searching"); return; } // 正常处理数组的代码... });
代码优化建议
改用Async/Await替代回调
回调嵌套会降低代码可读性,把fetchData改成返回Promise的形式:
// api.js export const fetchData = async function (URL) { const res = await fetch(`${URL}&appid=${api_key}`); if (!res.ok) throw new Error(`请求失败: ${res.status}`); const data = await res.json(); if (data.cod && data.cod !== 200) { throw new Error(data.message || '未知API错误'); } return data; }; // app.js searchTimeout = setTimeout(async () => { try { searchField.classList.add("searching"); const locations = await fetchData(url.geo(searchField.value)); if (!Array.isArray(locations)) { searchResult.innerHTML = '<p class="error">未找到匹配地点</p>'; return; } // 处理locations数组的代码... } catch (err) { console.error(err); searchResult.innerHTML = `<p class="error">${err.message}</p>`; } finally { searchField.classList.remove("searching"); } }, searchTimeoutDuration);
修复搜索防抖逻辑
你当前的searchTimeout ?? clearTimeout(searchTimeout)写法有误,应该改成:
// 无论超时是否存在,都清除之前的定时器 if (searchTimeout) clearTimeout(searchTimeout);
??是空值合并运算符,仅当searchTimeout为null/undefined时才执行右侧代码,无法清除已存在的超时任务。
内容的提问来源于stack exchange,提问作者Sambhav Jain
相关产品推荐
相关产品推荐

