1

我猜这更像是一个逻辑问题而不是 RxJS 问题,但我不知道如何解决它。

[输入 1] 从城市流中,我将收到 1 或 2 个对象(城市 1 或城市 2 是测试装置)。
如果只有一种语言可用,则为 1 个对象,同时具有两种语言的城市为 2 个对象。

[输入 2] 我也有一个 selectedLanguage(“fr”或“nl”)

【算法】 如果对象的语言对应selectedLanguage,我会采摘城市。当我收到 2 个对象(cities2)时,这适用于我的 RxJS 但是因为我也可以收到 1 个对象,所以过滤器不是正确的做法

[问题] 如果只有一个对象存在,我是否应该首先检查城市流并添加另一个对象。或者有什么更好的 RxJS/逻辑选项?

const cities1 = [
    {city: "LEUVEN", language: "nl"}
];

const cities2 = [
    {city: "BRUSSEL", language: "nl"},
    {city: "BRUXELLES", language: "fr"}
    ];

const selectedLang = "fr"
const source$ = from(cities1);
const result = source$.pipe(
    mergeMap((city) => {
        return of(selectedLang).pipe(
            map(lang => {
                return {
                    lang: city.language,
                    city: city.city,
                    selectedLang: lang
                }
            }),
            filter(a => a.lang === selectedLang),
            pluck('city')
        )
    }
    )
);
result.subscribe(console.log)

4

2 回答 2

0

感谢您的回复。这对我来说很有价值。事实上,我会忘记 selectedLang$ 并像常规字符串一样传递它。 问题1解决了

我将更详细地解释我的问题。我的 observable$ city$ 实际上是一个 GET 并且总是返回 1 或 2 两行。

leuven:
[ { city: 'LEUVEN', language: 'nl', selectedLanguage: 'fr' } ]

brussel:
[
  { city: 'BRUSSEL', language: 'nl', selectedLanguage: 'fr' },
  { city: 'BRUXELLES', language: 'fr', selectedLanguage: 'fr' }
]

如果它返回两行,我将能够过滤掉正确的值

filter(city => city.language === selectedLang) => BRUXELLES when selectedLangue is "fr"

但万一我只收到一排,我应该总是返回这个城市。

不使用 if 语句的最佳解决方案是什么?我一直在尝试使用对象破坏并扫描数组,但结果始终是一条记录。

// HTTP get
const leuven: City[] = [ {city: "LEUVEN", language: "nl"} ];

// same HTTP get
const brussel: City[] = [ {city: "BRUSSEL", language: "nl"},
                          {city: "BRUXELLES", language: "fr"}
                        ];

mapp(of(brussel), "fr").subscribe(console.log);

function mapp(cities$: Observable<City[]>, selectedLanguage: string): Observable<any> {
    return cities$.pipe(
        map(cities => {
            return cities.map(city => { return {...city, "selectedLanguage": selectedLanguage }}
            )
        }),
        // scan((acc, value) => [...acc, { ...value, selectedLanguage} ])
    )
}
于 2021-01-19T18:44:09.817 回答
0

如果 selectedLang 不是可观察的(即您不希望更改此值),那么我认为如果将其保留为值会更容易:

const result = source$.pipe(
   filter(city => city.language === selectedLang)
   map(city => city.city)
);

使用外部参数并没有错,它使流更易于阅读。

现在,如果 selectedLang 是一个可观察的对象,并且您希望结果始终给出具有该 selectedLang 的城市,那么您可能需要合并两个流,同时保留到目前为止收到的所有城市:

const selectedLang$ = of(selectedLang); // This is actually a stream that can change value
const cities$ = source$.pipe(
   scan((acc, city) => [...acc, city], [])
);

const result = combineLatest([selectedLang$, cities$]).pipe(
   map(([selectedLang, cities]) => cities.find(city => city.language == selectedLang)),
   filter(found => Boolean(found))
   map(city => city.city)
)

编辑:请注意,每次 city$ 或 selectedLang$ 更改并且其中一个城市匹配时,都会发出此结果。如果你不想重复,你可以使用distinctUntilChanged()操作符 - 可能这可以使用排气映射或其他东西进行优化,但它会使 IMO 更难阅读。

于 2021-01-19T10:09:29.870 回答