setInterval调用Promise首次正常后续报Unexpected identifier错误
问题产生原因
核心错误出在setInterval的参数传递逻辑:
- 代码中写
setInterval(app.playerNow().then(data => { app.dataOnAir(data); }), 5000)时,JS引擎执行到这行代码就会立刻调用app.playerNow(),将该异步方法返回的Promise对象作为第一个参数传给setInterval,而非传入「需要定时执行的函数」。 - 首次调用能正常返回结果,是因为这行代码初始化运行时就立刻触发了第一次
playerNow()请求,能正常走then回调执行后续逻辑。 - 从第二次定时触发开始,
setInterval会尝试将传入的Promise对象当作可执行函数运行,Promise本身不是可执行函数,再加上原代码没有处理请求失败的分支,异常状态的Promise会抛出未捕获错误,最终触发[object Promise] "Uncaught SyntaxError: Unexpected identifier"报错。
额外隐患:原代码中playerNow方法仅在response.ok为真时返回数据,请求失败时会返回值为undefined的Promise,后续执行dataOnAir时也可能触发参数异常问题。
修复方案
- 将
setInterval的第一个参数改为包裹异步请求逻辑的回调函数,保证定时器每次触发时才执行请求,而非初始化时就执行请求把返回值当回调传入。 - 增加异常捕获逻辑,覆盖网络错误、接口状态异常、JSON解析错误等边界场景,避免未捕获的Promise错误抛到全局。
- 增加空值判断,避免请求失败返回空值时,后续执行业务逻辑报错。
修复后的完整代码如下:
var app = { init : function() { app.start(); }, start : function() { // 传入可执行回调函数,定时器触发时才执行内部逻辑 setInterval(async () => { try { const data = await app.playerNow(); if (data) { app.dataOnAir(data); } } catch (err) { console.error('定时获取播放数据失败:', err); } }, 5000); }, playerNow : async function() { let url = "https://www.radiomatese.it/script/app/details.php"; let response = await fetch(url); if(response.ok){ let data = await response.json(); return data; } // 请求状态异常时抛出错误,交由外层捕获处理 throw new Error(`接口请求失败,状态码:${response.status}`); }, dataOnAir : function(data){ // 原有业务逻辑 } }
内容的提问来源于stack exchange,提问作者Massimiliano Comunale
相关产品推荐
相关产品推荐

