Promise - 是否可以强制取消 Promise

2024-01-01

我使用 ES6 Promises 来管理所有网络数据检索,在某些情况下我需要强制取消它们。

基本上,场景是这样的,我在 UI 上进行预先输入搜索,其中请求委托给后端必须根据部分输入执行搜索。虽然此网络请求 (#1) 可能需要一点时间,但用户继续键入,最终会触发另一个后端调用 (#2)

这里#2自然优先于#1,所以我想取消Promise包装请求#1。我已经在数据层中缓存了所有 Promise,因此理论上我可以在尝试提交 #2 的 Promise 时检索它。

但是,当我从缓存中检索到 Promise #1 后,如何取消它呢?

有人能建议一种方法吗?


在现代 JavaScript 中 - 不

承诺已经解决(哈),而且似乎永远不可能取消(待定)承诺。

相反,有一个跨平台(节点、浏览器等)取消原语,作为 WHATWG(也构建 HTML 的标准机构)的一部分,称为AbortController。您可以使用它来取消功能返回承诺而不是承诺本身:

// Take a signal parameter in the function that needs cancellation
async function somethingIWantToCancel({ signal } = {}) {
  // either pass it directly to APIs that support it
  // (fetch and most Node APIs do)
  const response = await fetch('.../', { signal });
  // return response.json;

  // or if the API does not already support it -
  // manually adapt your code to support signals:
  const onAbort = (e) => {
    // run any code relating to aborting here
  };
  signal.addEventListener('abort', onAbort, { once: true });
  // and be sure to clean it up when the action you are performing
  // is finished to avoid a leak
  // ... sometime later ...
  signal.removeEventListener('abort', onAbort);
}

// Usage
const ac = new AbortController();
setTimeout(() => ac.abort(), 1000); // give it a 1s timeout
try {
  await somethingIWantToCancel({ signal: ac.signal });
} catch (e) {
  if (e.name === 'AbortError') {
    // deal with cancellation in caller, or ignore
  } else {
    throw e; // don't swallow errors :)
  }
}

不,我们还不能这么做。

ES6 Promise 不支持取消yet。它正在路上,它的设计是很多人都努力工作的。Sound取消语义很难正确,而且这项工作正在进行中。关于“fetch”存储库、esdiscuss 和 GH 上的其他几个存储库存在有趣的争论,但如果我是你,我会耐心等待。

但是,但是,但是..取消真的很重要!

是的,事实是取消是really客户端编程中的一个重要场景。您所描述的情况(例如中止网络请求)很重要,而且无处不在。

所以……语言把我搞砸了!

是的,对此感到抱歉。在指定进一步的事情之前,必须先承诺 - 所以他们没有一些有用的东西,比如.finally and .cancel- 不过,它正在通过 DOM 达到规范。取消是not事后想来,这只是时间限制和 API 设计的迭代方法。

那我能做什么呢?

您有多种选择:

  • 使用第三方库,例如bluebird https://github.com/petkaantonov/bluebird他们的行动速度比规范快得多,因此可以取消以及其他一些好处 - 这就是像 WhatsApp 这样的大公司所做的事情。
  • 通过取消token.

使用第三方库是非常明显的。至于令牌,您可以让您的方法接受一个函数,然后调用它,如下所示:

function getWithCancel(url, token) { // the token is for cancellation
   var xhr = new XMLHttpRequest;
   xhr.open("GET", url);
   return new Promise(function(resolve, reject) {
      xhr.onload = function() { resolve(xhr.responseText); });
      token.cancel = function() {  // SPECIFY CANCELLATION
          xhr.abort(); // abort request
          reject(new Error("Cancelled")); // reject the promise
      };
      xhr.onerror = reject;
   });
};

这会让你做:

var token = {};
var promise = getWithCancel("/someUrl", token);

// later we want to abort the promise:
token.cancel();

您的实际用例 -last

对于令牌方法来说这并不太难:

function last(fn) {
    var lastToken = { cancel: function(){} }; // start with no op
    return function() {
        lastToken.cancel();
        var args = Array.prototype.slice.call(arguments);
        args.push(lastToken);
        return fn.apply(this, args);
    };
}

这会让你做:

var synced = last(getWithCancel);
synced("/url1?q=a"); // this will get canceled 
synced("/url1?q=ab"); // this will get canceled too
synced("/url1?q=abc");  // this will get canceled too
synced("/url1?q=abcd").then(function() {
    // only this will run
});

不,像 Bacon 和 Rx 这样的库在这里并不“闪耀”,因为它们是可观察的库,它们只是具有与用户级承诺库相同的优势,不受规范约束。我想我们会等着看 ES2016 中可观察对象何时原生化。他们are不过对于提前输入来说很漂亮。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Promise - 是否可以强制取消 Promise 的相关文章

  • 在 React 组件中动态创建元素

    我创建了一个辅助函数 当我单击按钮时 它可以在组件中动态创建元素 但是它没有显示我尝试附加到父 div 的 html 的一半 它正确地将标签添加为 html 但其余部分只是纯文本 谁能明白为什么吗 用于动态创建内容的函数 function
  • 单击传单形状时如何获取它的图层类型?

    我的 Leaflet 项目允许用户绘制形状 线条 矩形和多边形 用户可以单击形状来获取其统计数据 面积 周长等 我在我的FeatureGroup 上尝试了一个点击事件 其中添加了我绘制的所有形状 我不确定这是否是最好的方法 然后单击后 将调
  • 图表外的 JQPlot 图例

    我正在使用 JQPlot 并且在一个 HTML 页面上有很多图表 每个图表都有相同的图例 我的问题是 是否可以完全在图表之外显示图例 并在 HTML 页面或自己的 div 中拥有自己的位置 legend show true renderer
  • Javascript dispatchEvent click 在 IE9 和 IE10 中不起作用

    我正在尝试在 ExtJs 中构建应用程序时模拟鼠标事件 例如单击 鼠标悬停等 我使用下面的代码来模拟点击 function triggerEvent element eventName if document createEvent var
  • 使用 Nestjs 和 typeorm 保存实体的审核

    我有一个实体Audit就像下面在 Nestjs 应用程序中使用 typeorm for mongodb 一样 Entity export class Audit Column createdBy string BeforeInsert se
  • 如何使用 jQuery 在悬停元素旁边显示一个 div?

    假设我有severaldiv 像这样 EDIT div class ProfilePic a href img src lib css img profile pic1 png alt class ProfilePicImg a div c
  • IE9:奇怪的 JavaScript 错误

    我尝试在网站中显示 Google DFP 广告横幅时遇到错误 这些广告在除 IE9 之外的所有浏览器中展示 您可以在此处查看带有横幅的简单测试页面 离线演示 错误是 抛出异常但未捕获 google ads js 第 34 行字符 474 I
  • 在 Angular 2+ 中进行 DOM 操作的正确方法

    我知道有一些类似的问题 但没有人回答我的问题 基本上 以角度方式操作 DOM 的正确方法是什么 比如说我有这个 html
  • Javascript:一般访问函数参数

    这是我所拥有的 var log function arg1 arg2 console log inside arg1 arg2 var wrap function fn return function args console log be
  • Javascript 搜索并替换包含方括号的字符序列

    我正在尝试在字符串 Nationality EN ESP 中搜索 EN 我想从字符串中删除它 所以我使用替换方法 代码示例如下 var str Nationality EN ESP var find EN var regex new Reg
  • 在 JQueryUI 小部件的 QUnit 测试中测试可见性

    这对于其他人来说可能是显而易见的 但我没有通过搜索找到它 所以在这里发布问题和一个可能的答案 背景 使用自定义 JQuery UI 小部件小部件工厂 http jqueryui com widget 在小部件中 某些元素根据其他数据 选项隐
  • Svg 点击事件无法正常工作

    我试图让我的 SVG 看起来像一个 饼形 看起来一切都很好 此外 我希望它们每个都有不同的点击事件 function one alert 1 function two alert 2 function three alert 3 funct
  • 在 for 循环中突破 Promise 块

    我有以下代码 this storeNameValidate function stores var deferred q defer console log stores for storeIndex in stores this name
  • Select2 触发器(“更改”)创建无限循环

    假设页面上有两个 select2 元素 都使用 onChange 为了以编程方式在一个 select2 元素中设置一个值 您可以使用 id1 val xyz trigger change 如果您在这两个元素之一中进行选择时想要将另一个元素重
  • 函数声明可以出现在 JavaScript 的语句内部吗?

    请考虑将官方 ECMAScript 规范作为您答案的来源 而不是特定浏览器供应商发布的文档 我知道 Mozilla 用 函数语句 扩展了它的 JavaScript 实现 因此 根据 ECMAScript 规范 因此 其中定义的语法产生式 这
  • 以编程方式访问使用数据 URI 作为源的 iframe

    我正在使用 数据 URI 以编程方式创建一个 iframe 该框架加载良好 但似乎以编程方式使用 iframe 会遇到跨域安全检查 var iframeDoc document getElementById myFrame contentW
  • 如何使我的响应式网站在手机上支持“请求桌面网站”?

    我有一个响应灵敏的动态网站 Java Servlet 驱动且完全手工编码 由于它是一个返回数据表的科学站点 因此某些选项在较小的视口宽度下不可用 然而 可能有些用户更喜欢在桌面网站上挣扎才能访问这些选项 我希望适应他们 我的问题是 对于 i
  • 为什么事件属性不容易获取?

    我有以下代码 HERE https jsfiddle net 5n2zagjc 2 是可编辑的示例 用法 在输入字段中键入并观看控制台 function test event let keys Object keys event let k
  • Google Maps JavaScript API v3 方向功能

    我使用 Google Maps js API v3 我可以根据路径点显示方向this http code google com intl hu apis maps documentation directions Waypoints 我想要
  • 未终止的字符串文字

    我有一个 php 脚本 可以在我的服务器上上传 mp3 文件 我使用 上传 有一个事件 onSelect 文档 http www uploadify com documentation events onselect 当文件上传时调用 使用

随机推荐

  • 如何删除cumulo实例?

    我在通过调用初始化accumulo时创建了一个实例累积初始化但现在我想删除该实例 并且我想创建一个新实例 任何人都可以帮忙做到这一点吗 从 HDFS 中删除 ACCUMULO HOME conf accumulo site xml 中的 i
  • AgGrid 自定义 html 拖动

    我只是在考虑更改 ag 网格组件的拖动悬停 我找不到太多关于它的信息 有人知道如何在拖动模式下更改行的样式吗 我的目标是拥有不同的动画 整行 例如材质 UI UX https material io design components li
  • 为什么带有 EL 2.2 的 JSF 2.x 允许 MethodExpression 代替 ValueExpression?

    我看到几个问题询问如何将参数传递给 JSF 方法 在 EL2 2 和 servlet 3 0 中 它允许用户将参数传递到方法调用中 一个例子 如何从渲染的 h outputText 将参数传递给方法 https stackoverflow
  • C++11 std::thread 接受带有右值参数的函数

    我有一些作业 并且我很难理解 可能 如何将参数传递给 std thread 构造函数 假设以下代码 我删除了不需要的部分 template
  • 使用.net core 3.0进行脚本动态编译和运行代码

    我想提供在 NET core 3 中编译和运行代码 Csharp 类 的可能性 以用于脚本编写 脚本 类 应从文件系统加载并注入现有 静态 程序集中 https laurentkempe com 2019 02 18 dynamically
  • Javascript 函数将印度货币数字转换为支持 paise 的单词

    还有比这更快的解决方案吗 在花了一些时间谷歌搜索和玩弄其他人的代码之后 我做了一个快速修复 可重用函数适用于最大 99 99 99 999 的数字 number2text 1234 56 将返回ONE THOUSAND TWO HUNDRE
  • handleWatchKitExtensionRequest 未响应 Watchkit 扩展中的 openParentApplication (Swift)

    我正在尝试将信息从我的 WatchKit 应用程序发送到我的主要父应用程序 据我了解 我应该能够使用openParentApplication在我的 watchkit 扩展中 该扩展将由handleWatchKitExtensionRequ
  • 将 YUV 作为字节数组导入

    我正在开发一个项目 必须对 YUV420 SP NV21 图像 从 Android 相机拍摄 应用阈值 以确定哪些像素是 黑色 哪些像素是 白色 因此 我想将其作为字节数组导入 Python 中 使用 OpenCV NumPy PIL 这样
  • 如何从 bash 脚本在 GitHub 操作上创建输出?

    我有一个 GitHub 操作 本质上是一个 bash 脚本 我的操作的 javascript 部分执行 bash 脚本 const core require actions core const exec require actions e
  • 在模型上重复纹理

    我正在创建一个小游戏 你在迷宫中 迷宫的组织方式是2D Array 描述x and z position和block type 原来如此Tile based 假设每个块都是1 m 现在我的角色是2m高 迷宫应该是4m高的 因此 如果该瓷砖上
  • SQL查询多个AND和OR不起作用

    我有一个单元格 其中包含由双管分隔的值 我正在尝试使用以下内容搜索此单元格的内容 其中 10 是要搜索的数字 10 10 10 和 10 我的查询似乎只返回 10 没有其他变化 有人可以告诉我为什么它不起作用吗 提前谢谢了 您在下面看到的
  • 为什么从 python/uwsgi 内部调用时 `node.js` 会死掉?

    从外壳这个python启动并与之通信的代码node js过程工作正常 gt from subprocess import gt js function m console log m hello world gt out err Popen
  • 更改java的.class文件而不重新编译

    有什么办法可以做到以下几点 所以我有一个project jar 文件 在其中我需要修改传递给classA class 的某些方法的字符串 例如 假设这个 classA class 有一个名为 change String a String b
  • 检查 Postgres 复合字段是否为 null/空

    With Postgres 复合类型 http www postgresql org docs 9 2 static rowtypes html您基本上可以构建一个字段 其结构被定义为另一个表 我有一个名为 recipient 的复合字段
  • 错误:Angular 解析期间出现 Http 失败

    我正在学习 Angular 我想在 HTML 页面上显示 JSON 数据 错误是 Angular 解析期间 Http 失败 我不知道为什么请告诉我我的错误并给我链接如何显示多种类型的 JSON 数据 person component htm
  • MSBuild - 设置解决方案的属性

    我们在 VS2008 中使用 NET 3 5 我有一个包含约 20 个项目的解决方案 随着应用程序的增长和添加新模块 这个数字会随着时间的推移而增长 今天我需要为每个项目设置一个属性 我必须编辑每个 csproj 文件以添加以下内容
  • 如何避免在 Visual Studio 2017 中加载 Microsoft.VisualStudio.Threading 时出现错误

    我已在仅针对 Visual Studio 2019 的版本中对 Visual Studio 包进行了更新日志 我开始使用 NuGet 包的一项更改微软VisualStudio SDK 版本 16 0 202 并删除了许多对 DLL 的单独引
  • "aaaa".StartsWith("aaa") 返回 false

    如果这不是一个错误 那么任何人都可以解释这种行为背后的原因吗 事实上 似乎每个奇数个字母都会返回 false string test aaaaaaaaaaaaaaaaaaaa Console WriteLine test StartsWit
  • php oop文件上传

    我正在研究 oop php 文件上传脚本 很简单 但不起作用 问题是什么 我学习如何使用 FILE 以及如何编写 oop 风格的代码 Thanks upload php 是
  • Promise - 是否可以强制取消 Promise

    我使用 ES6 Promises 来管理所有网络数据检索 在某些情况下我需要强制取消它们 基本上 场景是这样的 我在 UI 上进行预先输入搜索 其中请求委托给后端必须根据部分输入执行搜索 虽然此网络请求 1 可能需要一点时间 但用户继续键入