React中每秒发起请求至res.readyToShow为true的实现及报错解决
问题描述
需求:在React中每秒发起一次fetch请求,直到返回结果res.readyToShow === true时停止请求,无法使用Socket或Webhooks。
执行代码后出现报错:
TypeError: Cannot read properties of undefined (reading 'test')
相关代码:
test = (ossUrn, md5Checksum) => setTimeout(() => { fetch( `google/isReadyToShow`,{ method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ urn: ossUrn, md5Checksum: md5Checksum, }), }) .then((response) => { response.json().then((res) => { console.log('response ', res); return (res.readyToShow) ? 0 : this.test(ossUrn, md5Checksum); }); }) .catch((err) => { console.log('err ', err); }); }, 2500);
return fetch( `google/translation`, { headers: { 'X-ACCESS-TOKEN-APP' : accessTokenApp, 'X-DRIVE-ID': e.itemData.id, 'X-FILE-NAME': e.itemData.name, 'X-FILE-TYPE': e.itemData.mimeType, 'X-FILE-MD5': e.itemData.md5Checksum, }, } ) .then((response) => { console.log("google item of id clicked " + e.itemData.id); response.json().then((res) => { console.log('response ', res); md5Checksum = e.itemData.md5Checksum; ossUrn = res.urn; console.log('URN ', ossUrn) console.log('URL', res); console.log('MD5', md5Checksum); // 执行检查文件是否准备好展示的函数 this.test(ossUrn, md5Checksum); }) .catch((err) => { console.log(err); }); }).catch(() => { throw new Error('Data Loading Error'); });
问题分析与解决
报错原因
报错核心是this指向异常:
- 在嵌套的
response.json().then()回调中,this没有绑定到React组件实例,导致调用this.test时this为undefined。 - 原代码使用嵌套
then的写法,不仅可读性差,还容易导致上下文丢失。
修正方案
1. 确保this指向正确
通过async/await替代嵌套then,既能提升代码可读性,又能保留组件上下文;同时新增定时器管理逻辑,避免内存泄漏。
修正后的完整代码
// 定义定时器变量,用于后续清理 checkTimer = null; test = async (ossUrn, md5Checksum) => { try { const response = await fetch(`google/isReadyToShow`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ urn: ossUrn, md5Checksum: md5Checksum, }), }); if (!response.ok) { throw new Error(`请求失败:${response.status}`); } const res = await response.json(); console.log('response ', res); if (!res.readyToShow) { // 未就绪则继续定时请求 this.checkTimer = setTimeout(() => this.test(ossUrn, md5Checksum), 2500); } else { // 就绪后清理定时器,执行后续逻辑 clearTimeout(this.checkTimer); console.log('文件已准备好展示'); // 这里可以添加就绪后的业务处理代码 } } catch (err) { console.log('err ', err); // 请求失败时清理定时器,避免无限重试 clearTimeout(this.checkTimer); } };
return fetch( `google/translation`, { headers: { 'X-ACCESS-TOKEN-APP' : accessTokenApp, 'X-DRIVE-ID': e.itemData.id, 'X-FILE-NAME': e.itemData.name, 'X-FILE-TYPE': e.itemData.mimeType, 'X-FILE-MD5': e.itemData.md5Checksum, }, } ) .then(async (response) => { console.log("google item of id clicked " + e.itemData.id); const res = await response.json(); console.log('response ', res); const md5Checksum = e.itemData.md5Checksum; const ossUrn = res.urn; console.log('URN ', ossUrn) console.log('URL', res); console.log('MD5', md5Checksum); // 执行检查函数 this.test(ossUrn, md5Checksum); }) .catch((err) => { console.log(err); throw new Error('Data Loading Error'); });
关键改进点
- 用
async/await替代嵌套then,避免上下文丢失,代码更易读; - 新增
checkTimer变量管理定时器,在请求就绪或失败时清理,防止内存泄漏; - 添加
response.ok检查,处理HTTP请求失败的场景; - 确保
this.test调用时上下文正确,箭头函数和async/await会保留组件实例的this指向。
内容的提问来源于stack exchange,提问作者meteor314
相关产品推荐
相关产品推荐

