Rx Swift discards .do(onNext: {}) 如何让它触发?
Rx Swift discards .do(onNext: {}) How do I make it trigger?
我正在尝试将我的 firebase
项目转换为与 rx swift
一起使用,但是 .do(onNext:{})
被丢弃,而 onCompleted
在 subscription
中触发.
我制作了 firebase
代码的 observable
函数:
func fetchFireBaseData() -> Observable<[Recipe]> {
return Observable.create({ [weak self] observer -> Disposable in
guard let self = self else { return Disposables.create() }
self.databaseRef.child(self.recipeType.description).observeSingleEvent(of: .value, with: { snapshot in
guard let data = snapshot.children.allObjects as? [DataSnapshot] else { return }
for item in data {
guard let thisItem = item.value as? NSDictionary else { return }
let tempRecipe = Recipe()
tempRecipe.fbKey = item.key
tempRecipe.recipeImageObject = (thisItem["recipeImageFirebase"] as? String) ?? ""
tempRecipe.recipeHeaderObject = (thisItem["recipeHeaderFirebase"] as? String) ?? ""
tempRecipe.recipeTextObject = (thisItem["recipeIngredientsTextFirebase"] as? String) ?? ""
self.recipeArray.append(tempRecipe)
}
observer.onNext(self.recipeArray)
})
observer.onCompleted()
return Disposables.create()
})
以及调用函数的部分:
func reloadContent() -> Observable<[Recipe]> {
guard let fbDataHandler = fbDataHandler else { return Observable.just([]) }
return fbDataHandler.fetchFireBaseData().do(onNext: { [weak self] value in
print("WHY ISNT THIS BEING CALLED?")
self?.content.accept(value.compactMap { RecipesCollectionViewCellViewModel(recipes: [=12=]) })
})
.do(onNext:
被忽略了,我不明白为什么。不过完成工作:
viewModel?.reloadContent().subscribe(onCompleted: {
print("THIS IS CALLED")
}).disposed(by: disposeBag)
知道为什么它不起作用吗?我在这里读到:https://github.com/ReactiveX/RxSwift/issues/1212那个
a.do(onNext: {
print([=14=]) // not called
}) <-- result is observable sequence that is discarded
但我不太确定这意味着什么或如何解决它。
编辑
好的,所以这可以用完成处理程序修复,但是 rx 的整个想法是在没有完成处理程序的情况下做这样的事情不是吗?
你的问题是你在调用 observeSingleEvent(of:with:)
后立即发出 onCompleted()
而没有给闭包一个被调用的机会。解决方案是在 onNext(_:)
.
之后调用闭包内的 onCompleted()
还有许多其他问题。如果 self
为空,这个 Observable 将永远不会发出任何东西,没有下一个事件,也没有任何错误或完成的事件。在 create 闭包中完全引用 self 的事实是一种糟糕的做法。在 create 闭包中定义 recipeArray
。
同时将 databaseRef
作为参数传递给函数,方法是将其设为高阶函数,或者将 class 的函数和扩展设为 databaseRef
的实例的。
另外,Recipe
不应该是 class。它应该是一个结构,因为它是一个值对象。
像这样:
extension Reactive where Base: DatabaseRef {
func fetchFireBaseData(recipeType: RecipeType) -> Observable<[Recipe]> {
Observable.create { observer in
base.child(recipeType.description)
.observeSingleEvent(of: .value, with: { snapshot in
guard let data = snapshot.children.allObjects as? [DataSnapshot] else {
observer.onError(DBError.noDataSnapshots)
return
}
let recipeArray = data.compactMap { (item) -> Recipe? in
guard let thisItem = item.value as? NSDictionary else { return nil }
return Recipe(
fbKey: item.key,
recipeImageObject: (thisItem["recipeImageFirebase"] as? String) ?? "",
recipeHeaderObject: (thisItem["recipeHeaderFirebase"] as? String) ?? "",
recipeTextObject: (thisItem["recipeIngredientsTextFirebase"] as? String) ?? ""
)
}
observer.onNext(recipeArray)
observer.onCompleted()
})
return Disposables.create()
}
}
}
我正在尝试将我的 firebase
项目转换为与 rx swift
一起使用,但是 .do(onNext:{})
被丢弃,而 onCompleted
在 subscription
中触发.
我制作了 firebase
代码的 observable
函数:
func fetchFireBaseData() -> Observable<[Recipe]> {
return Observable.create({ [weak self] observer -> Disposable in
guard let self = self else { return Disposables.create() }
self.databaseRef.child(self.recipeType.description).observeSingleEvent(of: .value, with: { snapshot in
guard let data = snapshot.children.allObjects as? [DataSnapshot] else { return }
for item in data {
guard let thisItem = item.value as? NSDictionary else { return }
let tempRecipe = Recipe()
tempRecipe.fbKey = item.key
tempRecipe.recipeImageObject = (thisItem["recipeImageFirebase"] as? String) ?? ""
tempRecipe.recipeHeaderObject = (thisItem["recipeHeaderFirebase"] as? String) ?? ""
tempRecipe.recipeTextObject = (thisItem["recipeIngredientsTextFirebase"] as? String) ?? ""
self.recipeArray.append(tempRecipe)
}
observer.onNext(self.recipeArray)
})
observer.onCompleted()
return Disposables.create()
})
以及调用函数的部分:
func reloadContent() -> Observable<[Recipe]> {
guard let fbDataHandler = fbDataHandler else { return Observable.just([]) }
return fbDataHandler.fetchFireBaseData().do(onNext: { [weak self] value in
print("WHY ISNT THIS BEING CALLED?")
self?.content.accept(value.compactMap { RecipesCollectionViewCellViewModel(recipes: [=12=]) })
})
.do(onNext:
被忽略了,我不明白为什么。不过完成工作:
viewModel?.reloadContent().subscribe(onCompleted: {
print("THIS IS CALLED")
}).disposed(by: disposeBag)
知道为什么它不起作用吗?我在这里读到:https://github.com/ReactiveX/RxSwift/issues/1212那个
a.do(onNext: {
print([=14=]) // not called
}) <-- result is observable sequence that is discarded
但我不太确定这意味着什么或如何解决它。
编辑 好的,所以这可以用完成处理程序修复,但是 rx 的整个想法是在没有完成处理程序的情况下做这样的事情不是吗?
你的问题是你在调用 observeSingleEvent(of:with:)
后立即发出 onCompleted()
而没有给闭包一个被调用的机会。解决方案是在 onNext(_:)
.
onCompleted()
还有许多其他问题。如果 self
为空,这个 Observable 将永远不会发出任何东西,没有下一个事件,也没有任何错误或完成的事件。在 create 闭包中完全引用 self 的事实是一种糟糕的做法。在 create 闭包中定义 recipeArray
。
同时将 databaseRef
作为参数传递给函数,方法是将其设为高阶函数,或者将 class 的函数和扩展设为 databaseRef
的实例的。
另外,Recipe
不应该是 class。它应该是一个结构,因为它是一个值对象。
像这样:
extension Reactive where Base: DatabaseRef {
func fetchFireBaseData(recipeType: RecipeType) -> Observable<[Recipe]> {
Observable.create { observer in
base.child(recipeType.description)
.observeSingleEvent(of: .value, with: { snapshot in
guard let data = snapshot.children.allObjects as? [DataSnapshot] else {
observer.onError(DBError.noDataSnapshots)
return
}
let recipeArray = data.compactMap { (item) -> Recipe? in
guard let thisItem = item.value as? NSDictionary else { return nil }
return Recipe(
fbKey: item.key,
recipeImageObject: (thisItem["recipeImageFirebase"] as? String) ?? "",
recipeHeaderObject: (thisItem["recipeHeaderFirebase"] as? String) ?? "",
recipeTextObject: (thisItem["recipeIngredientsTextFirebase"] as? String) ?? ""
)
}
observer.onNext(recipeArray)
observer.onCompleted()
})
return Disposables.create()
}
}
}