React组件中While循环内await异步执行异常导致无法退出问题
问题分析与修复方案
核心问题1:循环无法退出的原因
S3 ListObjectsV2(对应list-type=1)返回的IsTruncated字段是字符串类型的"true"或"false",而非布尔值。你直接将其赋值给isTruncated后,在while循环判断中,字符串"false"会被JavaScript视为true(非空字符串在布尔上下文里为真),导致循环永远无法终止。
核心问题2:await未正确等待的潜在原因
getBuilds方法中冗余的return Promise.resolve(iosJson);虽然不会直接导致await失效,但async函数本身会自动将返回值包装为Promise,这行代码属于多余操作,可能引发逻辑混淆。
具体修复步骤
1. 修正isTruncated的类型判断
在fetchKeys方法中,将字符串类型的IsTruncated转换为布尔值:
fetchKeys = async prefix => { let buildsArr = []; let marker= ''; let isTruncated = true; while (isTruncated) { const builds = await this.getBuilds(prefix, marker); if (builds.ListBucketResult.Contents) { builds.ListBucketResult.Contents.forEach(item => { buildsArr.push({'Key':item.Key, 'LastModified': item.LastModified}); }); } // 关键修改:将字符串转成布尔值 isTruncated = builds.ListBucketResult.IsTruncated === 'true'; console.log('isTruncated :: '+ isTruncated); if (isTruncated) { // 增加边界判断,避免Contents为空时报错 if (builds.ListBucketResult.Contents) { marker = builds.ListBucketResult.Contents.slice(-1)[0].Key; } else { // 极端情况强制终止循环 isTruncated = false; } } } return buildsArr; }
2. 简化getBuilds的返回逻辑
移除冗余的Promise.resolve,直接返回解析后的JSON:
async getBuilds(prefix, marker) { let uri = `/?list-type=1`; if (prefix) { uri += `&prefix=${prefix}`; } if (marker) { uri += `&marker=${marker}`; } console.log('URI is : '+ uri); const response = await get(uri, { baseURL: "https://s3.amazonaws.com/bucket-name" }); const iosXml = new DOMParser().parseFromString(response.data, 'text/xml'); const iosJson = parseXml(iosXml); // 直接返回,async函数自动包装为Promise return iosJson; }
3. 额外优化:避免组件生命周期警告
componentWillMount已被React标记为过时方法,建议替换为componentDidMount:
async componentDidMount() { await this.getAllBuilds(this.state.selectedApp); }
修改后,循环会正确识别isTruncated的布尔值并在合适时机退出,await this.getBuilds也会正确等待请求完成后再执行后续逻辑。
内容的提问来源于stack exchange,提问作者Mahtab Alam
相关产品推荐
相关产品推荐

