【前端炸裂新特性】Promise.all()要下岗了!Array.fromAsync()让异步代码一秒变优雅

130 阅读3分钟

在前端开发的日常工作中,处理异步数据一直是让人头疼的事。我们经常会用到 Promise.all() 搭配 map() 和 async/await 来批量处理异步请求,但这样写出来的代码往往又长又乱,不仅难维护,还容易出错。

更别说遇到异步生成器(async generator)或流(stream)时,Promise.all() 直接无能为力。现在,JavaScript 迎来了一位“救星”——Array.fromAsync(),它的出现让异步数组处理变得前所未有的简单和优雅。

Array.fromAsync() 是 ECMAScript 2024(ES2024)标准中新加入的静态方法。它的作用就是把“异步可迭代对象”或“类数组对象”直接转成真正的数组,而且还支持传入异步的 map 函数。

你可以把它理解为 Array.from() 的异步增强版,专门为现代异步场景量身定制。比如你要从多个 API 并发拉取数据、批量处理异步流、或者对每个数据项做异步转换,现在只需要一行 await Array.fromAsync() 就能全部搞定,再也不用 Promise.all() + map() 那种组合拳了。

Array.fromAsync() 的基本语法非常直观。你可以直接 await 它,把异步迭代的数据收集成数组。如果需要对每个元素做异步处理,还可以传一个 async 的 map 函数进去。例如:

const arr = await Array.fromAsync(asyncIterable, async (item) => {
  return await fetchData(item);
});

对比传统写法,之前我们通常是这样写的:

const results = await Promise.all(dataList.map(async (item) => {
  return await fetchData(item);
}));

现在,用 Array.fromAsync(),只需要一行,逻辑更清晰,结构更优雅。更重要的是,它原生支持 async generator 和流式数据,Promise.all() 做不到的事情,Array.fromAsync() 轻松拿下。

除了简化代码,Array.fromAsync() 还带来了很多开发体验上的提升。首先,它让异步数据收集变得更直观,读起来一目了然。其次,它支持 AbortController,可以优雅地中断长时间运行的异步任务,比如大批量的 fetch 请求。再者,它的 map 函数支持 await,可以直接异步转换每一项数据,无需额外封装。

当然,目前 Array.fromAsync() 已经被 Chrome 115+、Edge 115+ 和 Node.js 20.6+ 支持,Firefox 和 Safari 还在路上。实际开发中建议加一个特性检测,防止兼容性问题。例如:

if (Array.fromAsync) {
  // 安心用else {
  // 兼容写法或 polyfill
}

举个实际开发场景的例子:假如你在 Node.js 后端或者 React 前端,需要从分页 API 或流式接口批量拉数据,可以这样写:

async functionfetchPages() {
  for (let i = 1; i <= 5; i++) {
    yield await fetch(`https://api.example.com/data?page=${i}`).then(r => r.json());
  }
}

const allData = await Array.fromAsync(fetchPages());
console.log(allData);

一行 await,所有异步数据自动聚合成数组,开发体验直接升级。如果你经常和 API、流式数据、异步任务打交道,Array.fromAsync() 绝对值得你尝试。

总之,Array.fromAsync() 是 JavaScript 进化路上的又一颗重磅炸弹。它让异步数组收集和转换变得极其简单和优雅。以后写异步数据处理,再也不用为 Promise.all()、嵌套循环、回调地狱而烦恼了。试试 Array.fromAsync(),你一定会发现新世界!

如果你觉得这篇文章对你有帮助,欢迎关注「梦兽编程」微信公众号,获取更多前端黑科技和实战技巧。也欢迎转发给你的技术群,让更多同事告别繁琐代码,拥抱高效开发!

(完)