在 Array.filter 中正确使用 Async

本文译自How to use async functions with Array.filter in Javascript - Tamás Sallai。
0. 如何仅保留满足异步条件的元素
在第一篇文章中,我们介绍了 async / await 如何帮助处理异步事件,但在异步处理集合时却无济于事。在本文中,我们将研究该filter函数,它可能是支持异步函数的最直观的方法。
1. Array.filter
该filter函数仅保留通过条件的元素。它得到一个断言( predicate )函数,并且此函数返回 true / false 值。结果集合仅包含断言( predicate )返回 true 的元素。
const arr = [1, 2, 3, 4, 5];
const syncRes = arr.filter((i) => {
return i % 2 === 0;
});
console.log(syncRes);
// 2,4
2. filter 结合 map 使用
这次的异步版本要复杂一些,它分为两个阶段。第一个通过断言函数异步地映射数组,从而生成true / false 值。然后第二步是利用第一步的结果同步 filter

const arr = [1, 2, 3, 4, 5];
const asyncFilter = async (arr, predicate) => {
const results = await Promise.all(arr.map(predicate));
return arr.filter((_v, index) => results[index]);
}
const asyncRes = await asyncFilter(arr, async (i) => {
await sleep(10);
return i % 2 === 0;
});
console.log(asyncRes);
// 2,4
或单行实现:
const asyncFilter = async (arr, predicate) => Promise.all(arr.map(predicate))
.then((results) => arr.filter((_v, index) => results[index]));

并发
上面的实现同时运行所有断言函数。通常,这很好,但是与所有其他功能一样,它可能会使某些资源变得过分紧张。幸运的是,由于上述实现依赖于此map,因此可以使用相同的并发控件。
4. filter 结合 reduce 使用
除了使用异步map与同步之外filter,异步reduce 也可以完成这项工作。由于它只是一个功能,因此即使没有提供相同级别的控制,结构也更加容易。
首先,从一个空数组([])开始。然后通过断言函数运行下一个元素,如果通过则将其追加到数组。如果没有,请跳过它。

// concurrently
const asyncFilter = async (arr, predicate) =>
arr.reduce(async (memo, e) =>
await predicate(e) ? [...await memo, e] : memo
, []);

请注意,await predicate(e) 在 await memo 之前,这意味着这些将并行调用。
顺序处理
要在调用下一个谓词函数之前等待其结束,请更改await 的顺序:
// sequentially
const asyncFilter = async (arr, predicate) =>
arr.reduce(async (memo, e) =>
[...await memo, ...await predicate(e) ? [e] : []]
, []);
此实现等待上一个元素,然后根据断言(...[e]或...[])的结果有条件地附加一个元素。

5. 结论
虽然异步filter是可能的,但它最初的工作方式看起来很奇怪。尽管并发控制仍然可用,但与其他异步功能相比,它们需要更多的计划去控制它。
推荐阅读

在 Array.filter 中正确使用 Async的更多相关文章
- 如何在 Array.forEach 中正确使用 Async
本文译自How to use async functions with Array.forEach in Javascript - Tamás Sallai. 0. 如何异步遍历元素 在第一篇文章中, ...
- JavaScript笔记Array.filter(Boolean)
ECMAScirpt5 中 Array 类中的 filter 方法使用目的是移除所有的 ”false“ 类型元素 (false, null, undefined, 0, NaN or an empt ...
- js array filter pop push shift unshift方法
JavaScript Array filter() 方法 JavaScript Array 对象 实例 返回数组 ages 中所有元素都大于 18 的元素: var ages = [32, 33, ...
- array.fliter无法正确过滤出我想要的数组
var checked_list = state.files.filter(function(item, id){ // console.log('click the ' + item.id); re ...
- IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用
Autofac结合EF在MVC中的使用,上一篇IoC容器Autofac(4) - Autofact + Asp.net MVC + EF Code First(附源码)已经介绍了.但是只是MVC中Co ...
- 浅谈JavaScript中的defer,async
引言 开始重读<<JavaScript高级程序设计>>一书,看到关于JavaScript中关于defer.async的部分.网上查询了点资料,觉得蛮好的.现在总结下. defe ...
- 在Java filter中调用service层方法
在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null.如下所示: public class WeiXinFilter implements Filter ...
- 如何在Java Filter 中注入 Service
在项目中遇到一个问题,在 Filter中注入 Serivce失败,注入的service始终为null.如下所示: public class WeiXinFilter implements Filter ...
- android中正确导入第三方jar包
android中正确导入第三方jar包 andriod中如果引入jar包的方式不对就会出现一些奇怪的错误. 工作的时候恰好有一个jar包需要调用,结果用了很长时间才解决出现的bug. 刚开始是这样引用 ...
随机推荐
- failed to open directory
解决方法: 解决方案的路径不要包含中文!
- GO系列 | 5分钟入门GO【译】
什么是Google Go? Google Go是由Robert Griesmer,Rob Pike和Ken Thompson在Google设计的一种开源编程语言. Go在语法上类似于C语言: 除了内存 ...
- C++:利用全局钩子实现键盘锁
在家看网课,记笔记不方便.于是就想弄个键盘锁,方便学习(在寝室也好把外接键盘放上去打游戏). 其实这东西挺简单的,就三行代码. HHOOK hk; LRESULT CALLBACK kbproc(in ...
- 264. 丑数 II
编写一个程序,找出第 n 个丑数. 丑数就是只包含质因数 2, 3, 5 的正整数. 示例: 输入: n = 10输出: 12解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 ...
- TCP IP Socket In C, 2e-chapter 1 Introduction
本章是基础概念,建议补计算机网络基础,这里不全. 目录 1 网络,数据包,协议 2 关于地址(address) 2.1 IP地址格式 2.2 IPv4和IPv6共存 2.3 端口号 2.4 特殊地址 ...
- ADO.NET 的使用(一)
一.ADO.NET概要 ADO.NET 是一组向 .NET Framework 程序员公开数据访问服务的类. ADO.NET 为创建分布式数据共享应用程序提供了一组丰富的组件. 它提供了对关系数据.X ...
- ijkplayer中遇到的问题汇总
在做音频播放的时候,很多公司使用的是开源的ijkplayer播放器,ijkplayer底层是基于ffmpeg,在某机型上面可能常常遇到各种问题.今天整理了大家在使用ijkplayer中遇到的问题,以及 ...
- 详解聚类算法Kmeans的两大优化——mini-batch和Kmeans++
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是机器学习专题的第13篇文章,我们来看下Kmeans算法的优化. 在上一篇文章当中我们一起学习了Kmeans这个聚类算法,在算法的最后我 ...
- docker:一文学基础使用
目录 docker介绍 安装与镜像源配置 CentOS7 安装 设置镜像源 补充: 简单使用例子 基础概念 四个概念 镜像概念补充: 容器概念补充: 常用命令: 查看docker信息 镜像操作 容器操 ...
- settings插拔式源码
创建一个文件夹notify __init__.py import settings import importlib def send_all(content): for path_str in se ...