如何在指定超时时间终止不可修改的第三方Promise函数执行?
问题与解决方案
需求
给定不可修改的第三方函数thirdPartyFunction(返回Promise),实际执行时长可能长达30秒。需要实现:
- 达到固定超时时间时,阻止该函数的后续回调执行
- 确保超时后,该函数的
then回调不会运行任何无用代码
原代码
function sleep(t) { return new Promise((resolve, reject) =>{ setTimeout(() => { console.log('timeout!') return resolve({isTimeout: true}) }, t); }); } function thirdPartyFunction(t) { // thirdPartyFunction can't be edited return new Promise((resolve, reject) =>{ setTimeout(() => { console.log('thirdPartyFunction completed!') return resolve({success: true}) }, t); }); } function main() { return new Promise(async(resolve, reject) => { try { let thirdPartyFunctionExecutionTime = Math.floor(Math.random() * 10) + 1; thirdPartyFunction(thirdPartyFunctionExecutionTime * 1000, false).then( (r) => { console.log('should not execute this if thirdPartyFunctionExecutionTime > timeout') // only goal // other code which is not useful after timeout }); const timeout = 3; console.log(`thirdPartyFunctionExecutionTime: ${thirdPartyFunctionExecutionTime}, timeout - ${timeout}`) await sleep(timeout * 1000, true); throw 'stop main()' // return } catch (error) { console.log('in catch') return; } }) } main()
问题分析
原代码的核心问题是:thirdPartyFunction启动后,即使超时逻辑触发,其内部的异步操作(比如setTimeout)仍会在后台运行,最终触发resolve导致then回调执行,不符合需求。
解决方案代码
function sleep(t) { return new Promise((resolve, reject) =>{ setTimeout(() => { console.log('timeout!') reject(new Error('timeout')); // 超时直接抛出错误,配合Promise.race处理 }, t); }); } function thirdPartyFunction(t) { // thirdPartyFunction can't be edited return new Promise((resolve, reject) =>{ setTimeout(() => { console.log('thirdPartyFunction completed!') resolve({success: true}) }, t); }); } async function main() { let isTimeout = false; const thirdPartyFunctionExecutionTime = Math.floor(Math.random() * 10) + 1; const timeout = 3; console.log(`thirdPartyFunctionExecutionTime: ${thirdPartyFunctionExecutionTime}, timeout - ${timeout}`); try { // 用Promise.race让第三方函数和超时逻辑竞争执行 await Promise.race([ thirdPartyFunction(thirdPartyFunctionExecutionTime * 1000).then(r => { // 仅在未超时的情况下执行回调逻辑 if (!isTimeout) { console.log('thirdPartyFunction completed within timeout'); // 这里放置原本then回调里的有用代码 } return r; }), sleep(timeout * 1000).catch(err => { isTimeout = true; throw err; // 抛出超时错误,进入外层catch统一处理 }) ]); } catch (error) { console.log('in catch:', error.message); return; } } main();
方案说明
- Promise.race竞争执行:同时启动第三方函数和超时逻辑,谁先完成就优先执行谁的逻辑
- 超时标志位控制:超时触发时设置
isTimeout为true,第三方函数完成后会先检查该标志,仅在未超时的情况下执行回调代码 - 统一错误处理:超时逻辑直接
reject,触发外层catch块,集中处理超时情况
注意:如果要彻底终止第三方函数内部的异步操作(比如停止它的定时器),由于函数不可修改且未暴露取消接口,在JavaScript中无法实现。但上述方案已满足“超时后不执行无用回调”的核心需求。
内容的提问来源于stack exchange,提问作者ibexdev074
相关产品推荐
相关产品推荐

