JS Promise的resolve/reject失效?国旗匹配功能错误处理求助
问题分析与解决
核心问题
你代码里的fetch是异步任务,而判断found的代码是同步执行的——发起fetch请求后,还没等接口返回数据、还没来得及修改found的值,就直接执行了if(found)的判断,这时候found还是初始的false,所以每次都会触发reject。
修复方案
1. 把resolve/reject逻辑移到异步回调内
等fetch请求完成、数据处理完之后,再根据匹配结果决定是resolve还是reject,而不是在发起请求后立刻判断。
2. 移除全局found变量,避免状态污染
全局变量会保留上一次点击的状态,改用局部变量来记录是否找到匹配项。
3. 去掉正则的g修饰符
带g的正则表达式会维护一个lastIndex指针,多次调用test时会从上次结束的位置开始匹配,容易出现误判。
4. 复用首次请求的国家数据
页面加载时已经请求过一次API,没必要每次点击都重新请求,直接用之前存储的数据即可。
修改后的完整代码
const selector = document.getElementById('input') const btn = document.getElementById('btn') const flag = document.getElementById('content') const API = 'https://restcountries.com/v2/all' // 存储完整的国家对象,方便后续直接使用 let countries = [] // 页面加载时仅请求一次API fetch(API).then(data => data.json()).then(data => { countries = data console.log('国家数据加载完成') }) btn.addEventListener('click', () => { const info = selector.value.trim() // 空输入直接提示 if (!info) { console.error('请输入国家名称') return } // 用局部变量记录匹配状态,避免全局污染 let found = false // 只保留不区分大小写的修饰符,去掉g避免匹配异常 const reg = new RegExp(info, 'i') // 复用已加载的国家数据,无需重复请求API countries.forEach(element => { if (reg.test(element.name)) { flag.style.backgroundImage = `url(${element.flag})` flag.style.backgroundPosition = 'center' flag.style.backgroundSize = 'cover' found = true // 找到第一个匹配项就终止遍历,提升效率 return } }) const p1 = new Promise((res, rej) => { found ? res('匹配成功') : rej('未找到匹配的国家') }) p1.then(msg => console.log(msg)).catch(err => console.error(err)) })
额外优化点
- 加入空输入判断,避免无效匹配操作
- 找到第一个匹配项后终止遍历,减少不必要的循环开销
- 复用已请求的数据,大幅提升点击响应速度
内容的提问来源于stack exchange,提问作者maaarrr
相关产品推荐
相关产品推荐

