Promise.any()方法

选中文字可对指定文章内容进行评论啦,→和←可快速切换按钮,绿色背景文字可以点击查看评论额。

Promise.any()方法

Promise.any() 方法还接受一个可迭代的Promises,并在任何传入的 Promise 实现时返回一个fulfilled的 Promise。一旦Promise之一fulfilled,操作就会短路。 (这与 Promise.all() 正好相反,一旦一个 Promise rejected,操作就会短路。)下面是一个例子:

let promise1 = Promise.reject(43);

let promise2 = Promise.resolve(42);

let promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(44);
  }, 100);
});

let promise4 = Promise.any([promise1, promise2, promise3]);

promise4.then(value => console.log(value));

即使此示例中的第一个promise (promise1) 被拒绝,对 Promise.any() 的调用也会成功,因为第二个promise (promise2)已实现。 第三个promise(promise3)的结果被丢弃。

如果传递给 Promise.any() 的所有 Promise 都被拒绝,则返回的 Promise 会被 AggregateError 拒绝。 AggregateError 是一个错误,表示存储在 anerrors 属性中的多个错误。 例如:

let promise1 = Promise.reject(43);

let promise2 = new Promise((resolve, reject) => {
  reject(44);
});

let promise3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(45);
  }, 100);
});

let promise4 = Promise.any([promise1, promise2, promise3]);

promise4.catch(reason => {
  // Runtime dependent error message
  console.log(reason.message);

  // output rejection values
  console.log(reason.errors[0]); // 43
  console.log(reason.errors[1]); // 44
  console.log(reason.errors[2]); // 45
});

在这里,Promise.any() 接收到not fulfilled的 Promise,因此返回的 Promise 被 AggregateError 拒绝。 您可以检查 errors 属性,它是一个数组,以从每个 Promise 中检索rejection value。

 

Promise.any()使用场景

Promise.any() 方法最适用于您希望任何一个 Promise完成但是不在意有多少其他拒绝的情况,除非他们都拒绝。一下是一些使用场景

执行对冲请求

正如 The Tail at Scale² 中所定义的,对冲请求是客户端向多个服务器发出请求并接受来自第一个回复的响应的请求。 这在客户端需要尽可能低的延迟并且有专门用于管理额外负载和重复数据删除响应的服务器资源的情况下很有帮助。 这是一个例子:

const HOSTS = [
  "api1.example.com",
  "api2.example.com"
];

function hedgedFetch(endpoint) {
  return Promise.any(
    HOSTS.map(hostname => fetch(`https://${hostname}${endpoint}`))
  );
}

hedgedFetch("/transactions")
  .then(transactions => console.log(transations))
  .catch(reason => console.error(reason.message));

此示例保留了为每个对冲请求调用的主机数组。hedgedFetch() 函数根据这些主机名创建一个 fetch() 请求数组并传递该数组到 Promise.any()。 对于hedgedFetch() 的使用者来说,看起来好像只发出了一个请求,即使在幕后发生了多个请求。 这允许消费者仅使用一个fulfillment handler和一个rejection handler来处理结果。 如果任何一个请求失败,消费者永远不会知道; 只有当所有请求都失败时才会调用rejection hanlder。

 

在 Service Worker 中使用最快的响应

使用Service Worker的网页通常可以选择从何处加载数据:网络或缓存。 在某些情况下,网络请求实际上可能比从缓存加载更快,因此您可能希望使用 Promise.any() 来选择更快的响应。 下面的一些代码说明了 service worker 内部的这种模式:

self.addEventListener("fetch", event => {

	// get cached response
	const cachedResponse = caches.match(event.request);

	// fetch new response
	const fetchedResponse = fetch(event.request.url);

	// respond with the best option
	event.respondWith(
	  Promise.any([
	   fetchedResponse.catch(() => cachedResponse),
	   cachedResponse,
	   ])
	  .then(response => response ?? fetchedResponse)
	  .catch(() => {})
	);
});

fetch 事件侦听器允许您侦听网络请求并拦截响应。 此service worker示例使用 fetch 事件侦听器从缓存(使用 caches.match())和网络(使用 fetch())读取。 对 caches.match() 的调用会返回一个始终满足的promise,无论是使用匹配的响应对象,还是使用未定义的请求(如果请求不在缓存中)。 event.respondWith() 方法期望传递一个 Promise,因此这个事件处理程序传递 Promise.any() 的结果。

两个 Promise 被传递给 Promise.any():带有rejection handler的获取响应,默认返回缓存响应本身。 这样,缓存的响应如果存在且命中以及获取的响应rejected,则返回缓存响应。 然后,实现处理程序确保有一个有效的响应(请记住,如果缓存响应未命中,则响应可能是未定义的)。 拒绝处理程序不做任何事情,因为在这种情况下没有回退。 获取的响应和缓存的响应都被拒绝了,因此错误被静默忽略以允许浏览器使用其默认行为。

虽然 Promise.any() 在第一个fulfilled的promise后短路,但您可能还希望根据第一个settled的promise短路操作,而不管结果如何。

版权声明:著作权归作者所有。

相关推荐

检测iPhone X机型的方法

iPhone X即将上市。为了更好适配iPhone X,我们可能需要对iPhone做机型的判断。下面介绍两种方法:根据屏幕尺寸和方向判断这是iPhone机型列表。Swift 3if UIDevice().userInterfaceIdiom == .phone {      &n

Python安全创建目录的方法

在介绍Python安全创建目录之前,先举一个不安全创建目录的方式:if not os.path.exists(directory):     os.makedirs(directory) 在例子里,先判断目录是否存在,然后创建目录。这种方式是不安全的,它会导致竞争条件。在os.path.exists()和os.makedirs()之间的时

Swift 3/4缩放UIImage的方法

给UIImage添加extension(兼容Swift3 和Swift 4)extension UIImage {     func scaled(withSize size: CGSize) -> UIImage {   &nbs

Python比较字典的巧妙方法

Python里比较两个字典,可以比较两个字典有多少个是相同的键值对的。示例:>>> x = dict(a=1, b=6,c=3) >>> y = dict(a=2, b=2) >>> shared_items = set(x.items

Spring MVC获取请求header的方法

在Spring MVC有两种方法可以用来获取请求头Header的值。方法一、通过在方法的参数添加注解@RequestHeader示例如下:@Controllerpublic class RequestHeaderDemoController { @Autowired private HttpServletRequest request; @GetMapping("/prin

Ubuntu禁用systemd-resolved的方法

1、禁用并停止systemd-resolved的服务:sudo systemctl disable systemd-resolved.servicesudo systemctl stop systemd-resolved2、在/etc/NetworkManager/NetworkManager.conf文件的[main]中添加下面一行:dns=default3、删除链接:/etc/resolv.c

Python3 词典按值排序的方法

Python 3.6按值排序:x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}{k: v for k, v in sorted(x.items(), key=lambda item: item[1])}{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}按键排序只需要把item[1]改为item[0]x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}{

CKEditor5正确添加插件的方法

CKEditor5添加插件错误ckeditor-duplicated-modules本来想在CKEditor 5的ckeditor5-build-classic添加一个Code Block插件,按官方文档,先安装@ckeditor/ckeditor5-code-blocknpm install --save @ckeditor/ckeditor5-code-block然后再代码中引入使用:impo

CKEditor5 Observable——装饰方法

上一节我们学习了在CK5中,如何绑定多个属性以及绑定多个Observable对象,今天我们学习如何装饰方法。 首先,我们提出一个问题,为什么会有装饰方法呢?以及什么叫做装饰?所谓装饰,就是在不改变原来方法功能的前提下,增加方法的功能,众所周知在java的IO流中,就有很多地方用到了装饰。 而在CK5中,装饰是什么意思呢?请看下面这段话:Decorating object met