Node.js 在管道操作符之间保持对变量的访问

Node.js 在管道操作符之间保持对变量的访问,node.js,rxjs6,Node.js,Rxjs6,我一直在尝试在节点应用程序中使用RxjsfileList$是从fs.readdirsync(字符串数组)返回的 第一个map()有一个名为filename的参数 flatMap()readFileAsObservable()使用bindNodeCallback(fs.readFile)读取文件 我的类Testian需要2个参数;通过读取文件和第一个映射的文件名创建的对象。如何在我指示的管道中访问filename fileList$ .pipe( map((filename

我一直在尝试在节点应用程序中使用Rxjs
fileList$
是从
fs.readdirsync
(字符串数组)返回的

第一个
map()
有一个名为filename的参数

flatMap()readFileAsObservable()
使用
bindNodeCallback(fs.readFile)
读取文件

我的类
Testian
需要2个参数;通过读取文件和第一个映射的文件名创建的对象。如何在我指示的管道中访问
filename

fileList$
    .pipe(
        map((filename: string) => `${resolvedDirPath}/${filename}`),
        flatMap(
            (filePath: string) => readFileAsObservable(filePath, 'utf8') as Observable<string>
        ),
        map((fileData: string) => yaml.safeLoad(fileData) as ITestYaml),
        map((testYaml: ITestYaml) => new Testian(testYaml, [I want to use filename here])),
        flatMap((testYaml: Testian) => {
            const prom: Promise<{}> = activeTests.set(testYaml);
            outgoing.sendTest(testYaml);
            return from(prom);
        })
    )
文件列表$
.烟斗(
映射((文件名:字符串)=>`${resolvedDirPath}/${filename}`),
平面图(
(filePath:string)=>readFileAsObservable(filePath,'utf8')作为可观察
),
映射((fileData:string)=>yaml.safeLoad(fileData)作为ITestYaml),
map((testYaml:ITestYaml)=>newtestian(testYaml,[我想在这里使用文件名]),
平面图((testYaml:Testian)=>{
const prom:Promise=activeTests.set(testYaml);
outgoing.sendTest(testYaml);
从(prom)返回;
})
)

这在任何涉及链式函数的API中都会得到类似的处理,例如promises

临时变量 临时变量可用于存储超出应访问它的函数范围的值。这是一个简单但非惯用的解决方法:

let filename;

fileList$.pipe(
    map((_filename) => {
      filename = _filename;
      return `${resolvedDirPath}/${filename}`;
    }),
    flatMap((filePath) => readFileAsObservable(filePath, 'utf8')),
    map((fileData) => yaml.safeLoad(fileData)),
    map((testYaml) => new Testian(testYaml, filename)),
    flatMap((testYaml) => {
        const prom = activeTests.set(testYaml);
        outgoing.sendTest(testYaml);
        return from(prom);
    })
)
竞争条件可能存在问题,具体取决于可观察到的特定情况

嵌套函数 可以嵌套使用
filename
的函数,以从父范围访问变量:

fileList$.pipe(
    flatMap((filename) => of(`${resolvedDirPath}/${filename}`).pipe(
        flatMap((filePath) => readFileAsObservable(filePath, 'utf8')),
        map((fileData) => yaml.safeLoad(fileData)),
        map((testYaml) => new Testian(testYaml, filename)
    ),
    flatMap((testYaml) => {
        const prom = activeTests.set(testYaml);
        outgoing.sendTest(testYaml);
        return from(prom);
    })
)
传递值 在可能的情况下,该变量可以与其他结果一起传递:

fileList$.pipe(
    map((filename) => [filename, `${resolvedDirPath}/${filename}`]),
    flatMap(
        ([filename, filePath]) => forkJoin(filename, readFileAsObservable(filePath, 'utf8')),
    ),
    map(([filename, fileData]) => [filename, yaml.safeLoad(fileData) as ITestYaml)],
    map(([filename, testYaml]) => new Testian(testYaml, filename)),
    flatMap((testYaml) => {
        const prom = activeTests.set(testYaml);
        outgoing.sendTest(testYaml);
        return from(prom);
    })
)
异步..等待 如果流允许切换到promises和
async..wait
,则可以这样做,因为
async
函数中不存在函数作用域问题

fileList$.pipe(
    flatMap(async (filename) => {
      const filePath = `${resolvedDirPath}/${filename}`;
      const fileData = await readFileAsObservable(filePath, 'utf8').toPromise();
      let testYaml = yaml.safeLoad(fileData);
      testYaml = new Testian(testYaml, filename);
      const prom = activeTests.set(testYaml);
      outgoing.sendTest(testYaml);
      return prom;
    })
)

由于此observable已经使用了
flatMap
和Promissions,因此仅使用Promissions就可以安全地编写它。RxJS Observable有一些用例不适合承诺,但这不是其中之一。

我更喜欢您的异步..等待解决方案!实际上我只是在练习RxJs。谢谢你的洞察力,不客气。在这一点上,fileList$是非常无用的;它可以在异步函数中使用for..of进行迭代。可观测性很好,但在服务器端不太有用;承诺和节点流通常涵盖大多数情况。