这在任何涉及链式函数的 API 中都以类似方式处理,例如承诺。
临时变量
临时变量可用于存储超出应访问它的函数范围的值。这是一个简单但非惯用的解决方法:
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);
})
)
竞争条件可能存在问题,具体取决于特定的 observable。
嵌套函数
可以嵌套使用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);
})
)
异步..等待
如果流允许切换到 Promise 和 async..await,则可以这样做,因为 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 和 promise,它可以单独使用 promise 安全地编写。 RxJS observables 有一些不适合 promise 的用例,但这不是其中之一。