我有一些可观察的东西。而且我需要知道哪个触发了订阅。
Observable.combineLatest(
this.tournamentsService.getUpcoming(),
this.favoriteService.getFavoriteTournaments(),
this.teamsService.getTeamRanking(),
(tournament, favorite, team) => {
//what triggered combinelatest to run?
}).subscribe()
Run Code Online (Sandbox Code Playgroud) 在 RX dart 中,有一种RX.combineLatest使用回调函数组合流结果的方法。问题是它仅在每个流都发出值时才发出值。如果没有,则不会发射。
每当任何流序列发出一个项目时,都使用组合器函数将给定的流合并为单个流序列。 在所有流都发出至少一项之前,流不会发出。
我试图将多个流合并到一个流中进行验证,当流未发出或发出空值时,该验证应发出 false 或 true 。
class FormBloc {
final BehaviorSubject<bool> _result = BehaviorSubject();
final BehaviorSubject<String?> _usernameController = BehaviorSubject();
final BehaviorSubject<String?> _emailController = BehaviorSubject();
// Will only emit if each stream emitted a value
// If only username is emitted valid is not emitted
Stream<bool> get valid$ => Rx.combineLatest2(
_usernameController.stream,
_emailController.stream,
(username, email) => username != null || email != null
);
}
Run Code Online (Sandbox Code Playgroud)
我如何加入这些流,以便在任何流发生变化valid$时发出一个值?
我试图理解combineAll运算符是如何工作的.我正在使用官方文档中的以下示例:
import { take, map, combineAll } from 'rxjs/operators';
import { interval } from 'rxjs';
const source$ = interval(1000).pipe(take(2));
const example$ = source$.pipe(
map(val =>
interval(1000).pipe(
map(i => `Result (${val}): ${i}`),
take(5)
)
)
);
example$
.pipe(combineAll())
.subscribe(console.log);
Run Code Online (Sandbox Code Playgroud)
输出是:
["Result (0): 0", "Result (1): 0"]
["Result (0): 1", "Result (1): 0"]
["Result (0): 1", "Result (1): 1"]
["Result (0): 2", "Result (1): 1"]
["Result (0): 2", "Result (1): 2"]
["Result (0): 3", "Result (1): 2"]
["Result (0): 3", "Result (1): …Run Code Online (Sandbox Code Playgroud) 我刚刚遇到了自定义选择器,@ngrx我不能对这个功能感到惊讶.
继其使用情况books的selectedUser,我不能给一个真正的好理由使用自定义选择,例如:
export const selectVisibleBooks = createSelector(selectUser, selectAllBooks, (selectedUser: User, allBooks: Books[]) => {
return allBooks.filter((book: Book) => book.userId === selectedUser.id);
});
Run Code Online (Sandbox Code Playgroud)
而不是像:
export const selectVisibleBooks = Observable.combineLatest(selectUser, selectAllBooks, (selectedUser: User, allBooks: Books[]) => {
return allBooks.filter((book: Book) => book.userId === selectedUser.id);
});
Run Code Online (Sandbox Code Playgroud)
我试图说服自己的记忆化的createSelector是关键的部分,但据我了解,它不能执行这些性能提升到非原始值,因此它不会真正节省非原始切片任何计算,通过使用Rx' s distinctUntilChanged操作员combineLatest可以解决.
那么我错过了什么,我为什么要使用@ngrx/selector?
提前感谢任何见解.
我已经开始使用 Angular 中的 Jest Framework 进行单元测试已有一段时间了。然而,我陷入了需要对combineLatest RxJS 运算符进行单元测试的情况。我的组件如下所示。
成分:
public userData;
public productData;
constructor(
private readonly userService: UserService,
private readonly productService: ProductService
) {}
public ngOnInit() {
this.initialize();
}
public initialize() {
combineLatest([
this.userService.getUserData(),
this.productService.getProductData()
])
.subscribe([userData, productData] => {
this.userData = userData;
this.productData = productData;
});
}
Run Code Online (Sandbox Code Playgroud)
我已经嘲笑了我的服务,我的单元测试如下所示。
it('should initialize user and product data', fakeAsync(() => {
spyOn(userService, 'getUserData');
spyOn(productService, 'getProductData');
component.initialize();
tick();
fixture.detectChanges();
expect(userService.getUserData).toHaveBeenCalled();
expect(productService.getProductData).toHaveBeenCalled();
expect(component.userData).toBeDefined();
expect(component.productData).toBeDefined();
}));
Run Code Online (Sandbox Code Playgroud)
此测试失败并显示“已接收:未定义”。但是,当使用单个可观察值时,同样类型的测试也有效。
当我的组件加载时,我需要使用两个服务。两者都需要先完成,然后才能继续。这些步骤的完成顺序是随机的,不应顺序组成。设置遵循以下模式。
const observables = [
this.donkeyService.getDonkey(),
this.monkeyService.getMonkey()
];
combineLatest(observables)
.subscribe(([donkeyResult, monkeyResult]) => {
if (!!donkeyResult && !!monkeyResult) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
我们注意到结果没有按预期输入。我们花了一段时间才意识到它,但是donkeyResult的类型不是Donkey,尽管下面定义了服务器!
getDonkey() : Observable<Donkey> { ... }
Run Code Online (Sandbox Code Playgroud)
最终,我意识到,当元素传递到接收数组时,它们会失去类型,因为数组本身是any []。因此,我们按以下方式使用投射进行管理。
const observables = [
this.donkeyService.getDonkey(),
this.monkeyService.getMonkey()
];
combineLatest(observables)
.subscribe(([_1, _2]) => {
const donkeyResult = _1 as Donkey;
const monkeyResult = _2 as Monkey;
if (!!donkeyResult && !!monkeyResult) {
...
}
}
Run Code Online (Sandbox Code Playgroud)
我想重构代码,以便数组将保留服务方法签名指定的类型,并且不会合并为any的公分母。
是否可以使TypeScript和/或Rxjs具有一个数组,其中第一个元素是驴,第二个元素是Monkey?我可以使用与数组不同的数据结构吗?
我尝试了(当然失败了)很多不同的方法,包括像这样通过直接在数组中强制转换类型来四处寻找。
...
.subscribe(([_1 as …Run Code Online (Sandbox Code Playgroud) 我正在结合两个发布者来确定地图视图的中心坐标应该是什么。这两家出版商是:
CLLocationManager(开始发送位置更新后报告的第一个位置CLLocationManager)。在代码中:
class LocationManager: NSObject, ObservableObject {
// The first location reported by the CLLocationManager.
@Published var initialUserCoordinate: CLLocationCoordinate2D?
// The latest location reported by the CLLocationManager.
@Published var currentUserCoordinate: CLLocationCoordinate2D?
// What the current map view center should be.
@Published var coordinate: CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 42.35843, longitude: -71.05977) // Default coordinate.
// A subject whose `send(_:)` method is being called elsewhere every time the user presses a button to center the …Run Code Online (Sandbox Code Playgroud) 我有这个现实世界的场景。
我有一个 ReaderConfig 对象,它是 ReaderTheme、ReaderFont、ReaderFontSize 的哑元组。它的更改将触发 readerConfigObservable,然后重新绘制内容。
所以到目前为止的解决方案是
combineLatest(themeObservable, fontObservable, fontSizeObservable,
(theme, font, fontSize) -> new ReaderConfig(theme, font, fontSize))
Run Code Online (Sandbox Code Playgroud)
然而,因为这是android,ReaderTheme设置了一些android R.theme。东西,需要重新启动 Activity 才能生效。所以我还需要自行公开 themeObservable
themeObservable.subscribe(__ -> activity.recreate())
Run Code Online (Sandbox Code Playgroud)
由于它重新启动了 Activity,因此不需要触发 mergeLatest,它会触发重绘并分配资源,只是因为重新启动而在 1 秒后被处理掉。
因此,只有 fontObservable 和 fontSizeObservable 更改应该触发 mergeLatest,但是我确实需要最新的 themeObservable 值才能构造 ReaderConfig 对象。
我的解决方法是这样的
public Observable<ReaderConfig> readerConfigObservable() {
return Observable.combineLatest(
mFontRelay, mFontSizeRelay, (__, ___) -> createReaderConfig());
}
public ReaderConfig createReaderConfig() {
return new ReaderConfig(mThemeRelay.getValue(), mFontRelay.getValue(), mFontSizeRelay.getValue());
}
Run Code Online (Sandbox Code Playgroud)
所以基本上它在组合器函数中提取了themeObservable ,这并不是真正的反应性,对于这个异常用例有没有合适的解决方案?
我编写了如下小演示代码。我做了两个不同类型的PublishSubject。当我更改任何页面触发器时,仅当observable_page发生更改时,我才需要获取页面触发器。
class ViewController: UIViewController {
func loadData(page: Int, keyword: String) -> Observable<[Int]> {
let _result = Observable.of([1,2,3,4])
return _result
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let observable_keyword = PublishSubject<String>()
let observable_page = PublishSubject<Int>()
let trigger_tap = PublishSubject<Void>()
let tapObservable = trigger_tap.debug("trigger_tap", trimOutput: true)
let stringObservable = observable_keyword.debug("stringObservable", trimOutput: true)
let pageObservable = observable_page.debug("pageObservable", trimOutput: true)
let request_call_trigger = Observable.combineLatest(tapObservable, pageObservable)
.debug("request_call_trigger", trimOutput: true)
let page …Run Code Online (Sandbox Code Playgroud) 我观察到有关 JointLatest 的意外行为,如果内部发布者有subscribe(on:),则 JointLatest 流不会发出任何值。
笔记:
func makePublisher() -> AnyPublisher<Int, Never> {
Deferred {
Future { promise in
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + 3) {
promise(.success(Int.random(in: 0...3)))
}
}
}
.subscribe(on: DispatchQueue.global())
.receive(on: DispatchQueue.main)
.eraseToAnyPublisher()
}
var cancellables = Set<AnyCancellable>()
Publishers.CombineLatest(
makePublisher(),
makePublisher()
)
.sink { completion in
print(completion)
} receiveValue: { (a, b) in
print(a, b)
}.store(in: &cancellables)
Run Code Online (Sandbox Code Playgroud)
这是组合错误还是预期行为?您是否知道如何设置这种内部可以定义自己的订阅调度程序的流?
combinelatest ×10
rxjs ×4
angular ×3
observable ×3
swift ×3
combine ×2
android ×1
dart ×1
filter ×1
flutter ×1
ios ×1
jestjs ×1
ngrx ×1
redux ×1
rx-java ×1
rx-java2 ×1
rx-swift ×1
rxdart ×1
typescript ×1
unit-testing ×1