如何取消promise?
你无法直接“取消”一个 Promise。Promise 的运作方式是,一旦创建,它就会开始执行,并且其最终状态(resolved 或 rejected)是不可改变的。 你无法中途停止它的执行或改变它的结果。
然而,你可以采取一些策略来管理和处理不需要的 Promise 结果:
-
忽略 Promise 的结果: 这是最简单的做法。如果一个 Promise 的结果不再重要,你可以简单地忽略它,不注册
.then()
或.catch()
处理程序。Promise 仍然会执行完成,但你的代码不会对结果做出反应。 -
使用 AbortController (推荐方法,现代浏览器适用): AbortController 提供了一种更优雅的方式来发出取消信号。
const controller = new AbortController(); const signal = controller.signal; const myPromise = new Promise((resolve, reject) => { // 模拟一个耗时操作,例如 fetch 请求 fetch(url, { signal }) .then(response => { if (signal.aborted) { console.log('Fetch aborted'); return; // 或 reject(new DOMException('Aborted', 'AbortError')); } return response.json(); }) .then(data => resolve(data)) .catch(error => reject(error)); }); // ... 一段时间后 ... controller.abort(); // 发出取消信号
关键在于将
signal
对象传递给异步操作(例如fetch
)。在fetch
内部,你可以检查signal.aborted
是否为true
,如果是,则停止处理并返回或抛出一个错误。许多现代浏览器 API 都支持 AbortController。 -
使用 Promise.race() 超时或取消: 你可以使用
Promise.race()
让多个 Promise 竞争,并只处理第一个完成的 Promise。这可以用来实现超时或取消功能。const timeoutPromise = new Promise((_, reject) => { setTimeout(() => reject(new Error('Timeout')), 5000); // 5 秒超时 }); const myPromise = new Promise((resolve, reject) => { // ... 你的异步操作 ... }); Promise.race([myPromise, timeoutPromise]) .then(result => { // 处理 myPromise 的结果,如果它在超时之前完成 }) .catch(error => { if (error.message === 'Timeout') { console.log('Promise timed out'); } else { // 处理其他错误 } });
-
在异步操作内部进行取消检查 (特定场景): 如果你的异步操作是一个自定义函数,你可以在函数内部定期检查一个标志变量,如果标志被设置为取消,则停止操作。
let isCancelled = false; async function myAsyncOperation() { while (!isCancelled) { // ... 执行一部分操作 ... await new Promise(resolve => setTimeout(resolve, 100)); // 模拟延时 } console.log('Operation cancelled'); } const operation = myAsyncOperation(); // ... 一段时间后 ... isCancelled = true;
选择哪种方法取决于你的具体需求和代码环境。 AbortController
是最推荐的方法,因为它更加标准化和灵活。 对于不支持 AbortController
的旧版浏览器,你可以使用 Promise.race()
或手动检查取消标志。 记住,这些方法都不能真正“取消” Promise 的执行,而是让你可以控制如何处理 Promise 的结果。