如何在 JavaScript 中取消Promises?

科技   2024-10-22 10:10   上海  


JavaScript 中的 Promises 是管理异步操作的天赐之物,它提供了一种处理成功和失败的简洁方法。

但有一个微妙的挑战:从设计上讲,Promises 拥抱了其异步性质,一旦启动就无法直接停止。

在我们需要更精细控制的情况下,这可能会成为障碍,这时,我们就需要设计可取消的 Promises!

原始 Promise 的问题

想象一下获取大文件或发出网络请求。如果用户决定在中途取消,该怎么办?使用标准 Promise,会陷入困境。它会在后台继续运行,可能会浪费资源。

我们的目标:优雅取消

我们希望为我们的 Promise 提供以下功能:

  • 取消:发起取消请求。
  • 指示状态:了解 Promise 是否已成功取消或已解决。

TaskCancelable 解决方案

以下是我们可以实现 TaskCancelable 函数来增强我们的 Promise 的方法:

export const TaskCancelable = (task) => {  let _reject;  let isCancel = false;  const _status = Symbol("cancel");  const cancelP = new Promise((resolve, reject) => {    _reject = reject;  });  const p = Promise.race([task, cancelP]);
p.catch((reason) => { if (reason === _status) { isCancel = true; } }); p.cancel = () => { _reject(_status); return p; }; p.isCancel = () => { return isCancel; }; return p;};

解释 

Symbol("cancel"):我们使用 Symbol 来创建取消的唯一标识符。这可以防止与其他潜在错误发生冲突。

Promise.race([task, cancelP]):奇迹就在这里发生!我们将原始任务 Promise 与 cancelP Promise 进行比赛。先解决或先拒绝的一方获胜。

p.cancel():此自定义函数在调用时会拒绝 cancelP Promise,从而有效触发取消。

p.isCancel():这个方便的方法让我们可以检查 Promise 是否确实被取消。

实际示例 

让我们看看如何使用 TaskCancelable:

// Simulate a long-running taskconst longTask = new Promise((resolve) => {  setTimeout(() => {    resolve("Task complete!");  }, 3000);});
const cancellableTask = TaskCancelable(longTask);// Cancel after 1 secondsetTimeout(() => { cancellableTask.cancel(); }, 1000); cancellableTask .then((result) => console.log("Success:", result)) // Won't run .catch(() => { if (cancellableTask.isCancel()) { console.log("Task was cancelled!"); } else { console.log("Task failed for another reason"); } });

结论

通过创建可取消的 Promises,我们在管理异步操作方面获得了更大的灵活性。这种模式对于响应式用户界面和资源密集型任务至关重要,因为取消是这些任务的关键。



学习更多技能

请点击下方公众号



web前端开发
一个专业而懂你的前端开发技术研究学习平台,每天与你分享【web前端开发】相关的技术文章与案例,互联网资讯,编程图书与课程,前端开发工具等学习资源,坚持每天学习一点点,每天进步一点点,关注我们,一起学习成长进步。
 最新文章