Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在“过滤器”中使用可观察对象?_Javascript_Node.js_Rxjs_Rxjs6 - Fatal编程技术网

Javascript 如何在“过滤器”中使用可观察对象?

Javascript 如何在“过滤器”中使用可观察对象?,javascript,node.js,rxjs,rxjs6,Javascript,Node.js,Rxjs,Rxjs6,假设我有一个类似于以下内容的目录结构: foo | +---one | +---tmp | +---two | +---three | +---tmp 我想得到foo下的子目录列表,它下面有一个tmp(子)子目录。我有以下代码可以实现这一点: const { bindNodeCallback, from } = require('rxjs'); const { map, flatMap, filter } = require('rxjs/operators'); const

假设我有一个类似于以下内容的目录结构:

foo
|
+---one
|   +---tmp
|
+---two
|
+---three
    |
    +---tmp
我想得到
foo
下的子目录列表,它下面有一个
tmp
(子)子目录。我有以下代码可以实现这一点:

const { bindNodeCallback, from } = require('rxjs');
const { map, flatMap, filter } = require('rxjs/operators');
const { readdir, access, accessSync, constants: { F_OK, R_OK }} = require('fs');
const { join } = require('path');

const readdirRx = bindNodeCallback(readdir);

const FOO = './foo';

const result = readdirRx(FOO)
    .pipe(
        // readdir will return an array of files. Convert each
        // file into an observable, and then flatten it.
        flatMap(from),

        // get rid of directories that do not have a `tmp` dir underneath
        filter(dir => {
            try {
                accessSync(join(FOO, dir, 'tmp'), F_OK | R_OK);
                return true;
            } catch (err) {
                return false;
            }
        })
    );
result.subscribe(console.log, console.error, () => console.log('Done!'));
// outputs (correctly):
//   one
//   three
//   Done!
然而,这段代码在我看来很糟糕,因为(a)我对控制流使用异常,(b)存在一个同步的
accessSync
调用,这两个调用都对性能有害

我确实有下面一段代码来检查相同的东西:

const fileExistsAndReadableRx = bindNodeCallback(
    // check if file exists and readable
    (file, cb) => access(file, F_OK | R_OK,
        // call the callback with true if no errors found
        err => cb(!err)
    )
);
但是,我不知道如何将
fileexist和readablerx
插入上述程序。我的目标是删除try-catch块,并使用
fileexist和readablerx
来筛选出没有
tmp
(sub-)子目录的子目录。我该怎么做

(请注意,我尝试执行的实际任务不是读取磁盘。我尝试执行的是一个复杂的异步操作,我必须用一个更简单的示例来说明我的问题)

到目前为止,我所尝试的: 我试图使用
映射
,但它会发出一系列可观察的信息,正如人们所期望的那样:

const result = readdirRx(FOO)
    .pipe(
        flatMap(from),
        map(dir =>
            fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
        )
    );
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
//   Observable { _isScalar: false, _subscribe: [Function] }
//   Observable { _isScalar: false, _subscribe: [Function] }
//   Observable { _isScalar: false, _subscribe: [Function] }
//   Done!
const result = readdirRx(FOO)
    .pipe(
        flatMap(from),
        flatMap(dir => fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
            .pipe(
                filter(Boolean),
                map(() => dir),
            )
        ),
    );
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
//   true
//   Done!
所以我想,我知道!我会使用
flatMap
来展平观测值。这将产生三个布尔值,这些布尔值最终将从这些可观测值中发出。但这也不起作用。它只发出一个值:

const result = readdirRx(FOO)
    .pipe(
        flatMap(from),
        flatMap(dir =>
            fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
        )
    );
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
//   true
//   Done!
编辑: 我试过了,但那只产生了一个布尔值。不是我期望的字符串列表:

const result = readdirRx(FOO)
    .pipe(
        flatMap(from),
        map(dir =>
            fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
        )
    );
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
//   Observable { _isScalar: false, _subscribe: [Function] }
//   Observable { _isScalar: false, _subscribe: [Function] }
//   Observable { _isScalar: false, _subscribe: [Function] }
//   Done!
const result = readdirRx(FOO)
    .pipe(
        flatMap(from),
        flatMap(dir => fileExistsAndReadableRx(join(FOO, dir, 'tmp'))
            .pipe(
                filter(Boolean),
                map(() => dir),
            )
        ),
    );
result.subscribe(console.log, console.error, () => console.log('Done!'));
// Outputs:
//   true
//   Done!

您可以这样做:

readdirRx(FOO)
.烟斗(
平面图(来自),
flatMap(dir=>fileExistsAndReadableRx(join(FOO,dir,'tmp'))
.烟斗(
catchError(res=>of(res)),
过滤器(布尔),
映射(()=>dir),
)
),
)
它假设
fileexistandreadablerx
返回
Observable
filter(布尔)
只是
filter(v=>!!v)
的缩写

这里的技巧基本上就是您尝试的,即(平面)将每个目录映射到tmp文件夹的可观察检查。然后,我们使用该结果过滤掉那些不匹配的结果,然后将其映射回目录,而不是中间结果

你可以在这里看到它的作用:

您可能希望使用
cb(null,!err)
调用
fileExistsAndReadableRx中的回调


谢谢你的回答。但这会产生一个布尔值作为结果。(请参阅我的编辑)。哦,对于rxviz,@Krumia问题是,
文件exist和readablerx
不会发出真/假,而是会发出这些值的错误。我稍微更新了一下我的答案,有点不对劲;你可能想更好地解决这个问题。我现在已经不在电脑前了,但是你可能想用
cb(null,!err)
调用
fileexistandreadablerx
中的回调,而不是像在我的编辑中那样捕捉错误。就是这样,它是
cb(null,!err)
,而不是
cb(!err)
。我希望你不介意我在回答中添加你的评论,这样我就可以接受了。