partial.lenses:如何使用L.collect在光学中使用异步操作



我知道partial.lenses不一定是下面问题的最佳解决方案,这也是这个问题的重点所在。我试图使用partial.lenses库中的L.collect列出目录中的文件。目标只是获得一个扁平的文件名数组。

问题:我不想使用fs.readdirSync,而是想在我的光学系统中使用Node的fsneneneba API的异步、Promise返回版本。

以下将是readdir的承诺版本:

const util = require('util')
const fs = require('fs')
const readdirAsync = util.promisify(fs.readdir)

以下是实际实施情况。我想知道如何用异步版本替换readdir函数中的同步fs.readdirSync

const L = require("partial.lenses")
const fs = require("fs")
const path = require("path")
const _ = require("lodash")
const basePath = path.basename(`${__dirname}/..`)
const isDirectory = dirent => {
return dirent instanceof fs.Dirent ? dirent.isDirectory() : false
}
const readDir = path => () => {
return fs.readdirSync(path, { withFileTypes: true })
}
const leafs = nodePath => {
return L.cond(
[
_.isArray,
L.lazy(() => [
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[
isDirectory,
L.lazy(() => [
readDir(nodePath),
L.elems,
L.choose(({ name }) => leafs(path.join(nodePath, name)))
])
],
[L.identity]
)
}
const listFiles = async () =>
L.collect(
leafs(basePath),
fs.readdirSync(basePath, { withFileTypes: true })
)

这是一个有趣的问题,因为Partial Lenses可以处理类似这样的异步问题,但该库目前只提供直接支持开箱即用的异步操作。在将来图书馆肯定可以扩建,为执行异步操作。

局部透镜构建中的遍历应用操作。通过使用不同的应用程序不同的操作,如收集元素,计算元素的最小值,或计算数据结构。

许多操作,如收集元素或计算最小值,都有一个潜在的单胚。任何单半群,类似数组级联

const ConcatArray = {empty: () => [], concat: (l, r) => l.concat(r)}

可以转换为应用程序。在局部透镜中L.concatL.concatAs运营部门在内部这样做。

因此,对于异步收集元素,我们可以使用异步版本一个连接的monoid。我们可以通过创建一个函数将任意一个monoid转换为异步monoid:

const asyncMonoid = m => ({
empty: async () => m.empty(),
concat: async (l, r) => m.concat(await l, await r)
})

我们现在可以定义的异步版本L.collect如下:

const collectAsync = L.concatAs(
async x => [x],
asyncMonoid(ConcatArray)
)

为了解决这个问题,我们还需要一种方法来获得异步操作,以便我们可以使用光学放大。为此,我们可以定义一种新的原始光学等待的函数在光学成分中向前传递之前的焦点:

const awaitIt = async (x, i, F, xi2yF) => xi2yF(await x, i)

使用上面的awaitIt光学器件,我们现在可以定义异步遍历给定适当异步readDirectory的文件系统中的文件功能:

const filesUnderEntries = L.lazy(() => [
awaitIt,
L.elems,
L.ifElse(L.get('isDir'), ['path', filesUnderDirectory], 'path')
])
const filesUnderDirectory = [L.reread(readDirectory), filesUnderEntries]

我们可以使用上面的遍历来检查目录结构并选择文件。我们还可以进一步编写读取这些文件的操作并检查来自这些文件的数据。例如

collectAsync(
[
filesUnderDirectory,
L.when(R.test(/.my$/)),
L.reread(readFile),
awaitIt
]
)

定义一个异步操作,该操作遍历目录树并生成目录树下扩展名为CCD_ 8的文件的内容。

这里有一个游乐场,里面有完整的代码和使用伪造文件系统的示例操作。

最新更新