尝试返回对象数组时函数内for循环冻结问题及代码分析
咱们先拆解下你这段代码里导致循环提前终止(看起来像“冻结”)的核心问题,再一步步给出修复方案:
为什么循环会异常终止?
第一次循环就直接return,函数提前结束
你的seperateUri函数在for循环的第一次迭代里就执行了return this[i] = callback(result),这会直接终止整个函数的执行,循环自然只跑了一次就停了,根本不会处理后续的URI。嵌套定义的
callback完全冗余,还覆盖了参数
你在循环内部重新定义了callback函数,但这个函数只是返回一个对象,而且完全没用到函数开头传入的那个callback参数——相当于把参数覆盖了,完全没必要这么写。this的使用完全错误
在普通函数调用(seperateUri(uri))中,this默认指向全局对象(浏览器里是window),你给this[i]赋值其实是在污染全局变量,而不是收集解析结果。正则匹配存在缺陷
你的URI数组里每个链接前面都有空格,而原正则没有处理开头的空白字符,会导致匹配失败,result变成null,后续访问result[2]、result[3]会直接报错。另外,playlist类型的URI包含user/xxx/路径,原正则的分组逻辑也会把user当成类型,导致解析错误。var i的变量提升隐患
虽然这次因为提前return没暴露,但如果后续修复了return的问题,var声明的i会因为变量提升,导致循环结束后i的值是uri.length,引发意想不到的问题。
修复后的代码(同步返回对象数组)
如果你的需求是同步解析所有URI并返回对象数组,修复后的代码如下:
var uri = [' https://open.spotify.com/album/51vRvV83RdWGP9FpzGe4SQ ', ' https://open.spotify.com/user/diplomaddecent/playlist/6AvLNaeJ7qeF1Ur1kNoiXT ', ' https://open.spotify.com/user/spotify/playlist/37i9dQZF1DX4dyzvuaRJ0n '] function seperateUri(uriList) { // 修正正则:处理首尾空格,兼容playlist的user路径,正确分组类型和ID const parseUri = /^\s*https?:\/\/open.spotify.com\/(?:user\/\w+\/)?(\w+)\/(\w+)\s*$/i; const resultList = []; // 用let声明i,避免var的变量提升问题 for (let i = 0; i < uriList.length; i++) { const result = parseUri.exec(uriList[i]); if (result) { // 分组1是类型(album/playlist),分组2是ID resultList.push({ type: result[1], id: result[2] }); } else { // 处理匹配失败的情况,避免报错 resultList.push({ type: null, id: null, error: `Invalid URI: ${uriList[i]}` }); } } // 循环结束后统一返回结果,不再提前终止 return resultList; } // 调用测试 console.log(seperateUri(uri));
如果你确实需要使用callback(异步场景)
如果原函数设计的是异步回调模式(比如后续要加异步请求),可以调整为下面的版本,保留callback参数:
var uri = [' https://open.spotify.com/album/51vRvV83RdWGP9FpzGe4SQ ', ' https://open.spotify.com/user/diplomaddecent/playlist/6AvLNaeJ7qeF1Ur1kNoiXT ', ' https://open.spotify.com/user/spotify/playlist/37i9dQZF1DX4dyzvuaRJ0n '] function seperateUri(uriList, callback) { const parseUri = /^\s*https?:\/\/open.spotify.com\/(?:user\/\w+\/)?(\w+)\/(\w+)\s*$/i; const resultList = []; for (let i = 0; i < uriList.length; i++) { const result = parseUri.exec(uriList[i]); if (result) { resultList.push({ type: result[1], id: result[2] }); } else { resultList.push({ type: null, id: null, error: `Invalid URI: ${uriList[i]}` }); } } // 调用传入的回调函数返回结果 callback(null, resultList); } // 使用示例 seperateUri(uri, (err, results) => { if (err) { console.error('解析出错:', err); } else { console.log('解析结果:', results); } });
内容的提问来源于stack exchange,提问作者Happy Machine

