发布于 2026-01-06 1 阅读
0

空闲时使用函数式编程可达到 60fps

空闲时使用函数式编程可达到 60fps

替代文字

自发布以来, js-coroutines已经能够处理诸如解析和字符串化 JSON 或压缩空闲数据之类的标准函数,并将任务拆分到多个帧中,从而使所有内容都能以 60fps 的流畅度运行——现在它也具备了构建函数式管道的能力:

const process =
        pipe(
            parseAsync,
            mapAsync.with((v) => ({...v, total: v.units * v.price})),
            stringifyAsync,
            compressAsync        
        )
Enter fullscreen mode Exit fullscreen mode

这是一个虚拟例程,它解析一些 JSON,计算出项目的总值,将其存储回 JSON,并对其进行压缩。

然后我们就可以用我们的数据调用这个管道了:

   const compressedData = await process(inputJSON)
Enter fullscreen mode Exit fullscreen mode

该函数创建了一个异步进程,该进程与标准的js 协程pipe结合使用,在主线程上协同运行所有作业,从而确保有足够的时间进行动画和交互。

我们也可以插入自己想要拆分的计算:

      const process = pipe(
             parseAsync,
             function * (data) {
                let i = 0
                let output = []
                for(let item of data) {
                    output.push({...item, 
                       total: item.units * item.price,
                       score: complexScore(item)
                    })
                    if((i++ % 100)==0) yield
                }
                return output
             },
             tap(console.log),
             stringifyAsync
         )         
Enter fullscreen mode Exit fullscreen mode

这里我们将一个生成器函数放入流水线,并确保yield时不时地调用它。这个 yield 调用会检查我们是否有足够的时间继续执行,或者安排在下一个空闲时间恢复执行该函数。

新功能

功能 参数 目的
pipe ...function

每个函数可以是异步函数、普通函数或生成器。

该函数接收管道的当前值并对其进行处理。您可以使用该call()函数传递其他参数,例如映射函数mapAsync。js-coroutines 中的所有 xxxAsync 函数都有一个.with()可用于简化导入调用的函数,其效果相同。

创建一个异步函数来执行管道
tap function(current){...} 此函数会向管道添加一个函数,该函数接收当前值,但不返回结果。您可以使用它来实现诸如日志记录或保存之类的副作用。管道会暂停执行,直到该函数执行完毕。
branch function(current){...} 此函数向管道添加一个接收当前值的函数。您可以使用它来实现诸如日志记录或保存之类的副作用。管道不会暂停执行,因此会从此点开始形成一个新的延续。
repeat functiontimes 创建一个函数,该函数执行指定的函数次数。
call function...params 此函数允许调用另一个函数,该函数将接受管道的当前值,但需要额外的参数。提供的参数将附加到管道的当前值之后。

演示

文章来源:https://dev.to/miketalbot/js-function-programming-in-idle-time-3c57