这是在 angularfire2 中使用 rxjs MergeMap 的正确方法吗?
Is this the correct way to use rxjs MergeMap in angularfire2?
我是 angular 和 rxjs 的新手,
我正在尝试使用 angularfire2
和 rxjs
从 firebase
获取三个不同的值,并将其作为承诺 return。经过多次研究和尝试,我终于使用这段代码成功了。
这是代码(假设 afdb 是 angularfire-database):
getThreeValues() {
return this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
}),
mergeMap(first => {
return this.afdb.object('firebaseref2').valueChanges().pipe(
map(second => {
return ({first: first, second: second})
}),
take(1)
);
}),
mergeMap(firstsecond => {
return this.afdb.list('firebaseref3').valueChanges().pipe(
map(third => {
return ({...firstsecond, third: third})
}),
take(1)
);
}),
take(1))
.toPromise();
}
代码有效,我得到承诺,它解析为包含我需要的三个值的对象。
问题是我不确定这是否是最好的方法(因为我不确定这段代码是如何工作的)。
因为你很确定你只会取 .valueChanges()
的第一个值,所以将它们包装成 .forkJoin()
而不是全部 .mergeMapping
会更有效率方式。在 javascript 的 destructuring
的帮助下,您的代码可以看起来像这样简单得多:
getThreeValues() {
return forkJoin(
this.afdb.list('firebaseref1').valueChanges().pipe(take(1)),
this.afdb.object('firebaseref2').valueChanges().pipe(take(1)),
this.afdb.object('firebaseref3').valueChanges().pipe(take(1))
)
.pipe(
map(([first, second, third]) => ({
first: first.length,
second,
third
}))
).toPromise()
}
好吧,你很有创意,很好地解决了这个问题,但还有更有效的方法。我不知道你是想 运行 并行查询还是串行查询,但由于你的代码没有表明这三个查询是相关的(第二个查询从第一个获取数据),我将提供一个并行解决方案,这应该可以更快地解决。
使用combineLatest
import { combineLatest } from 'rxjs';
// returns promise of [value1, value2, value3]
return combineLatest(
this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
}),
take(1),
),
this.afdb.object('firebaseref2').valueChanges().pipe(
take(1),
),
this.afdb.object('firebaseref3').valueChanges().pipe(
take(1),
),
).toPromise();
或更简单(更少代码)的解决方案(可能的结果略有不同):
import { combineLatest } from 'rxjs';
return combineLatest(
this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
}),
),
this.afdb.object('firebaseref2').valueChanges(),
this.afdb.object('firebaseref3').valueChanges(),
).pipe(
take(1),
).toPromise();
您也可以使用 forkJoin 实现此目的。
firstCall(){
return this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
});
}
secondCall(){
return this.afdb.object('firebaseref2').valueChanges().pipe(
mergeMap(second => second),
take(1)
);
}
thirdCall(){
return this.afdb.object('firebaseref3').valueChanges().pipe(
mergeMap(third => third),
take(1)
);
}
const observables = [];
observables.push(this.firstCall());
observables.push(this.secondCall());
observables.push(this.thirdCall());
return forkjoin(observables).toPromise();
我是 angular 和 rxjs 的新手,
我正在尝试使用 angularfire2
和 rxjs
从 firebase
获取三个不同的值,并将其作为承诺 return。经过多次研究和尝试,我终于使用这段代码成功了。
这是代码(假设 afdb 是 angularfire-database):
getThreeValues() {
return this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
}),
mergeMap(first => {
return this.afdb.object('firebaseref2').valueChanges().pipe(
map(second => {
return ({first: first, second: second})
}),
take(1)
);
}),
mergeMap(firstsecond => {
return this.afdb.list('firebaseref3').valueChanges().pipe(
map(third => {
return ({...firstsecond, third: third})
}),
take(1)
);
}),
take(1))
.toPromise();
}
代码有效,我得到承诺,它解析为包含我需要的三个值的对象。
问题是我不确定这是否是最好的方法(因为我不确定这段代码是如何工作的)。
因为你很确定你只会取 .valueChanges()
的第一个值,所以将它们包装成 .forkJoin()
而不是全部 .mergeMapping
会更有效率方式。在 javascript 的 destructuring
的帮助下,您的代码可以看起来像这样简单得多:
getThreeValues() {
return forkJoin(
this.afdb.list('firebaseref1').valueChanges().pipe(take(1)),
this.afdb.object('firebaseref2').valueChanges().pipe(take(1)),
this.afdb.object('firebaseref3').valueChanges().pipe(take(1))
)
.pipe(
map(([first, second, third]) => ({
first: first.length,
second,
third
}))
).toPromise()
}
好吧,你很有创意,很好地解决了这个问题,但还有更有效的方法。我不知道你是想 运行 并行查询还是串行查询,但由于你的代码没有表明这三个查询是相关的(第二个查询从第一个获取数据),我将提供一个并行解决方案,这应该可以更快地解决。
使用combineLatest
import { combineLatest } from 'rxjs';
// returns promise of [value1, value2, value3]
return combineLatest(
this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
}),
take(1),
),
this.afdb.object('firebaseref2').valueChanges().pipe(
take(1),
),
this.afdb.object('firebaseref3').valueChanges().pipe(
take(1),
),
).toPromise();
或更简单(更少代码)的解决方案(可能的结果略有不同):
import { combineLatest } from 'rxjs';
return combineLatest(
this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
}),
),
this.afdb.object('firebaseref2').valueChanges(),
this.afdb.object('firebaseref3').valueChanges(),
).pipe(
take(1),
).toPromise();
您也可以使用 forkJoin 实现此目的。
firstCall(){
return this.afdb.list('firebaseref1').valueChanges().pipe(
map(data => {
return data.length;
});
}
secondCall(){
return this.afdb.object('firebaseref2').valueChanges().pipe(
mergeMap(second => second),
take(1)
);
}
thirdCall(){
return this.afdb.object('firebaseref3').valueChanges().pipe(
mergeMap(third => third),
take(1)
);
}
const observables = [];
observables.push(this.firstCall());
observables.push(this.secondCall());
observables.push(this.thirdCall());
return forkjoin(observables).toPromise();