You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MLB API异步数据存储异常:数组索引调用返回undefined

问题分析与解决方案

首先,你的问题主要来自两个核心点:异步请求的执行时机,以及对MLB API返回数据结构的误解,咱们一步步拆解解决:

1. 异步请求的执行顺序坑点

你代码里的console.log(jsonData)写在getData.send()之后,但XMLHttpRequest是异步操作——也就是说send()触发请求后,浏览器会在后台处理请求,而主线程代码会继续往下跑,这时候onload回调还没触发,jsonData还是个空数组。

你在控制台能看到完整数据,是因为浏览器控制台会保留对数组的引用,当后续onload回调填充了数组后,控制台会自动更新显示内容,但实际在console.log执行的那一刻,数组是空的。如果把console.log(jsonData)移到onload回调内部,就能看到正确的、已填充的数组了。

2. MLB API的数据结构误解

MLB的这个搜索接口返回的JSON不是直接的球员数组,而是多层嵌套的结构。比如你请求Judge的数据,返回的简化结构大概是这样:

{
  "search_player_all": {
    "queryResults": {
      "totalSize": "1",
      "row": [
        {
          "player_id": "592450",
          "name_last": "JUDGE",
          "name_first": "AARON",
          // 其他球员属性...
        }
      ]
    }
  }
}

你现在把整个外层响应对象push到了jsonData数组里,所以jsonData[0]对应的是这个大对象,而不是单个球员。控制台显示的属性路径["0"],其实是这个外层对象的索引,不是球员数组的索引。

修正后的代码

我们可以直接提取出里面的球员数组,而不是存储整个响应对象:

let lastName = 'judge'; 
let getData = new XMLHttpRequest; 
let jsonData = []; 

function getPlayer () { 
  getData.open('GET', `http://lookup-service-prod.mlb.com/json/named.search_player_all.bam?sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`, true); 
  getData.onload = function() { 
    if (this.status === 200) { 
      // 提取嵌套的球员数组
      const response = JSON.parse(this.responseText);
      const rawPlayers = response.search_player_all.queryResults.row;
      // 兼容单球员结果(API会把row返回为对象而非数组)
      jsonData = Array.isArray(rawPlayers) ? rawPlayers : [rawPlayers];
      // 现在可以正常访问第一个球员了
      console.log('第一个球员:', jsonData[0]);
    } 
  } 
  getData.send(); 
}

更优的JSON数据处理方案

现在更推荐用fetch API替代XMLHttpRequest,它基于Promise,语法更简洁,异步流程更易维护:

let lastName = 'judge'; 
let jsonData = []; 

async function getPlayer() {
  try {
    const response = await fetch(`http://lookup-service-prod.mlb.com/json/named.search_player_all.bam?sport_code='mlb'&active_sw='Y'&name_part='${lastName}%25'`);
    if (!response.ok) throw new Error(`请求失败: ${response.status}`);
    const data = await response.json();
    const rawPlayers = data.search_player_all.queryResults.row;
    jsonData = Array.isArray(rawPlayers) ? rawPlayers : [rawPlayers];
    console.log('第一个球员:', jsonData[0]);
  } catch (error) {
    console.error('获取数据出错:', error);
  }
}

async/await让异步代码看起来像同步代码,可读性更强,还能方便地捕获请求错误。另外要注意:当搜索结果只有一个球员时,MLB API会把row返回为单个对象,所以必须用Array.isArray做兼容处理,避免后续数组操作报错。

内容的提问来源于stack exchange,提问作者Brent Kulwicki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:24:39