60fps JS 同时对数百万条记录进行排序、映射和减少(使用空闲时间协程) js-coroutines 更新协程 在此处获取库:它是如何工作的?

2025-05-25

60fps JS,同时对数百万条记录进行排序、映射和减少(使用空闲时间协程)

js-协程

更新协程

在这里获取库:

它是如何工作的?

js-协程

GitHub

我之前在 dev.to 上读到一些非常有趣的东西后,突然灵光一闪- 给了我一个想法 - 而且哇,它真的有效!

我问了自己这个问题:

什么时候在 JavaScript 应用的主线程上对大型数组进行排序才合适?当然,只要你不介意用户看到所有动画和特效卡顿,任何时候都可以。即使转移到工作线程,也会因为序列化而影响主线程,导致一切卡顿。

那么什么时候才是合适的时机呢?嗯,就是在所有动画没有任何动作、系统空闲的间隙里。如果你能写点东西来消耗这段时间,然后把控制权交给系统,让它可以执行动画并完成剩下的工作,然后在下一个间隙继续执行就好了。现在你可以……

现在支持异步 JSON请参阅后续文章!

等等,还有更多!

使用协程的另一个超级实用的方法是制作动画并控制复杂的状态——js-coroutines 也提供了强大的update方法,可以以高优先级运行每一帧。见下文。

它配备了最有用的数组函数:

  • forEach
  • 地图
  • 筛选
  • 减少
  • 查找索引
  • 寻找
  • 一些
  • 每一个
  • 种类
  • 追加(数组到数组)
  • concat(将两个数组合并为一个新数组)

这个辅助函数yielding将一个普通函数包装成一个生成器,并每隔几次迭代检查一次剩余时间。你可以在上图中看到它的用法。但它只是一个辅助函数——如果你的map函数需要做更多工作,它本身可以是一个生成器,在需要的时候 yield,也可以将结果传递给更深层的、可以 yield 的函数:

const results =
  yield *
  map(inputArray, function* (element, index) {
    //Every 200 indices give up work
    //on this frame by yielding 'true'
    //yield without true, checks the amount
    //of remaining time
    if (index % 200 === 199) yield true;

    //Yield out a filter operation
    let matched = yield* filter(
      element,
      yielding((c) => c > 1000)
    );

    //Now yield out the calculation of a sum
    return yield* reduce(
      matched,
      yielding((c, a) => c + a),
      0
    );
  });
Enter fullscreen mode Exit fullscreen mode

yielding(fn, [optional yieldFrequency]) -> function *

更新协程

实现状态动画的一个好方法是使用每帧运行的协程。在这种情况下,当你yield在下一帧被回调时,状态动画就变得轻而易举了:

import { update } from "js-coroutines";

//Animate using a coroutine for state
update(function* () {
  while (true) {
    //Move left to right
    for (let x = -200; x < 200; x++) {
      logoRef.current.style.marginLeft = `${x * multiplier}px`;
      yield;
      //Now we are on the next frame
    }
    //Move top to bottom
    for (let y = 0; y < 200; y++) {
      logoRef.current.style.marginTop = `${y * multiplier}px`;
      yield;
    }
    //Move diagonally back
    for (let x = 200; x > -200; x--) {
      logoRef.current.style.marginLeft = `${x * multiplier}px`;
      logoRef.current.style.marginTop = ((x + 200) * multiplier) / 2 + "px";
      yield;
    }
  }
});
Enter fullscreen mode Exit fullscreen mode

替代文本

正如您在此性能捕获中所看到的,排序和处理均匀分布在各个帧中,保持 60fps。

在这里获取库:

GitHub

或者

npm i js-coroutines
Enter fullscreen mode Exit fullscreen mode

执照

js-coroutines - MIT (c) 2020 Mike Talbot

它是如何工作的?

点击此处查看后续文章

文章来源:https://dev.to/miketalbot/60fps-js-while-sorting-mapping-and-reducing-millions-of-records-with-idle-time-coroutines-10pg
PREV
用强大的咖喱函数为你的 JavaScript 增添趣味!(函数式编程与咖喱函数)
NEXT
我编写了 14 个函数来转储 lodash 并减少捆绑包大小......