Restful API偶发调用失败且catch语句异常触发问题排查与解决方案咨询
问题:API请求无数据时的异常处理优化
我们通过RESTful API获取正在进行的电竞赛事信息,偶尔会出现页面加载完成但API未返回任何数据的情况。我怀疑问题出在API本身,但还是想确认我们的代码是否存在问题。另外让我困惑的是,无论API是否返回数据,catch语句都会触发,控制台会输出"error"。我想添加无数据返回时的替代处理方案,请问该方案是否应放在catch语句中?如果是,如何实现仅在请求实际失败时才触发catch语句?
我们的代码:
const proxyurl = "https://cors-anywhere.herokuapp.com/"; const url = "http://datafeed.bet/en/esports.json "; fetch(proxyurl + url) .then(response => response.json()) .then(data => { const list = data; const games = list && list.Sport && list.Sport.Events && list.Sport.Events.map((match) => match.Name.substr(0, match.Name.indexOf(",")) ); const uniqueGames = [...new Set(games)]; let combinedMatches = []; data && data.Sport && data.Sport.Events && data.Sport.Events.map((game) => { game.Matches.map((match) => { match.Logo = game.Logo; match.TournamentName = game.Name; match.CategoryID = game.CategoryID; match.ID = game.ID; }); combinedMatches = combinedMatches.concat(game.Matches); }); this.setState({ gameData: data, games: games, uniqueGames: uniqueGames, preloading: false, filteredGames: combinedMatches, allMatches: combinedMatches, count: Math.ceil(combinedMatches.length / this.state.pageSize), }); var i; let allMatches = 0; let temp; for (i = 0; i < this.state.filteredGames.length; i++) { temp = allMatches = allMatches + this.state.filteredGames[i].Matches.length; } this.setState({ allMatches: allMatches }); }) .catch(console.log('error');
解答:
首先先解决你的核心困惑:为什么catch总是触发
你的catch写法有语法错误!你直接写了.catch(console.log('error');,这会导致代码在初始化fetch请求链的时候,就立刻执行console.log('error'),根本没把它当成错误回调函数。正确的写法应该是把函数传入catch,比如:
.catch(error => { console.log('请求错误:', error); });
这就是为什么不管请求成功与否,你都会看到"error"输出——这段代码和请求结果完全无关,只是在代码加载时就执行了一次。
接下来处理API无数据返回的场景:
这种情况不属于请求失败(只要HTTP状态码是2xx,fetch就会认为请求成功),所以不会进入catch块,你需要在第二个then里手动判断数据是否有效:
- 在业务逻辑开始前添加数据校验:
.then(data => { // 校验数据是否存在且结构符合预期 if (!data || !data.Sport || !data.Sport.Events || data.Sport.Events.length === 0) { // 无数据时的处理逻辑 this.setState({ preloading: false, filteredGames: [], allMatches: 0, count: 0, noData: true // 可以加个状态标识无数据,方便页面提示 }); console.log('API未返回有效赛事数据'); return; // 终止后续业务代码执行 } // 原来的业务逻辑继续执行 const list = data; const games = list.Sport.Events.map((match) => match.Name.substr(0, match.Name.indexOf(",")) ); // ... 剩下的代码 })
- 修复后的
catch块只会处理真正的请求错误(比如网络断连、HTTP 4xx/5xx错误、JSON解析失败等):
.catch(error => { console.error('请求过程发生错误:', error); // 请求失败时的兜底处理 this.setState({ preloading: false, filteredGames: [], allMatches: 0, count: 0, requestFailed: true }); });
另外给你两个小的代码优化建议:
- 遍历
data.Sport.Events时用forEach替代map,因为你只是做数据拼接,不需要返回新数组,forEach的语义更清晰 - 计算总赛事数可以用
reduce简化循环:
const totalMatches = combinedMatches.reduce((sum, item) => sum + (item.Matches?.length || 0), 0); this.setState({ allMatches: totalMatches });
内容的提问来源于stack exchange,提问作者phunder
相关产品推荐
相关产品推荐

