Object.groupBy不能直接用于API响应,因它要求输入为已解析的数组而非Promise;须先await获取响应、.json()解析,并处理包装结构、嵌套字段及类型统一等问题。
因为 Object.groupBy 要求传入一个可迭代对象(如数组),且回调函数必须返回一个有效分组键;但多数 API 返回的是 Promise,不是数组,更不是已解析的 JSON 数据流。直接写 Object.groupBy(fetch('/api/logs'), x => x.status) 会报 TypeError: undefined is not iterable——fetch 返回的是 Promise,不是数据本身。
常见错误现象:控制台显示 Cannot use 'in' operator to search for 'length' in [object Promise],本质是把 Promise 当成了数组传给了 Object.groupBy。
await 获取响应体,再 .json() 解析成数组{ data: [...] } 这类包装格式),否则要先提取 res.data
Object.groupBy 不支持逐行解析,得用 ReadableStream + TextDecoder 手动拆分业务 API 的返回格式五花八门,Object.groupBy 对输入极其敏感:键函数一旦对 undefined 或 null 调用,就会分到 undefined 组里,导致状态码丢失。
[{id:1,status:200},{id:2,status:500}] → 直接 Object.groupBy(data, x => x.status)
{data:[...],total:10} → 必须先取 res.data,别漏掉这层{id:1,detail:{code:404}} → 键函数得写成 x => x.detail?.code ?? 0,避免 Cannot read property 'code' of undefined
参数差异直接影响分组结果:用 x.status 和 String(x.status) 会产生 {200:[...], "200":[...]} 两个不同键——数字和字符串不等价,务必统一类型。
当一次请求返回上千条日志,且状态码分布极不均匀(比如 99% 是 200,剩下 1% 散落在 4xx/5xx),Object.groupBy 本身无性能问题,但后续遍历容易踩坑。
Object.groupBy,Firefox 和旧版 Edge 完全不支持,必须加 core-js 或手写降级逻辑new Date(x.timestamp).getDay()),它会被调用 N 次;状态码这种原始字段最安全Object.groupBy,先映射再分组:data.map(x => ({...x, bizGroup: authCodes.has(x.status) ? 'auth' : 'other'}))
示例:降级写法(兼容所有环境)
const groupBy = (arr, keyFn) => { const groups = {}; for (const item of arr) { const key = keyFn(item); if (!groups[key]) groups[key] = []; groups[key].push(item); } return groups;};
当 API 使用 text/event-stream 或 application/x-ndjson 返回实时日志流时,Object.groupBy 完全失效——它只接受一次性数组,不支持增量更新。
ReadableStream + Response.body 接收流,配合 TextDecoderStream 解码JSON.parse 后立即按状态码写入对应 Map:groups.get(x.status)?.push(x) ?? groups.set(x.status, [x])
Map 配合 Proxy 或信号库(如 valtio)容易被忽略的一点:流式场景下,状态码可能重复出现,但分组逻辑必须幂等;不要假设第一次出现的 500 就是“首个错误”,它只是当前批次里的一个样本。