- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我有 2 个嵌套的 Observable Streams,它们执行 HTTP 请求。现在我想显示加载指示器,但无法使其正常工作。
var pageStream = Rx.createObservableFunction(_self, 'nextPage')
.startWith(1)
.do(function(pageNumber) {
pendingRequests++;
})
.concatMap(function(pageNumber) {
return MyHTTPService.getPage(pageNumber);
})
.do(function(response) {
pendingRequests--;
});
Rx.createObservableFunction(_self, 'search')
.flatMapLatest(function(e) {
return pageStream;
})
.subscribe();
search();
nextPage(2);
nextPage(3);
search();
这将触发 pendingRequests++
4 次,但 pendingRequests--
只会触发一次,因为 flatMapLatest
会在前 3 个 HTTP 之前取消内部 observable响应到达。
我找不到类似 onCancel
回调的任何东西。我还尝试了 onCompleted
和 onError
,但它们也不会被 flatMapLatest
触发。
还有其他方法可以实现吗?
谢谢!
示例:单个 search()
调用。
示例:search()
和 nextPage()
调用。 (在 search() 响应返回之前调用了 nextPage()。)
示例:search()
、search()
。 (search() 调用相互覆盖,尽管第一个调用的响应可以被忽略)
示例:search()
、nextPage()
、search()
。 (再说一遍:因为第二次search(),前面search()和nextPage()的响应可以忽略)
示例:search()
、nextPage()
。但是这次 nextPage() 是在 search() 响应返回后调用的。
我尝试使用pendingRequests
计数器,因为我可以同时有多个相关 请求(例如:search()、nextPage()、nextPage ()
)。然后,当然我想在所有相关请求完成后禁用加载指示器。
调用search()、search()
时,第一个search()是无关紧要的。这同样适用于 search()、nextPage()、search()
。在这两种情况下,只有一个事件的相关请求(最后一个 search()
)。
最佳答案
使用 switchMap
又名 flatMapLatest
,您希望在新的外部项到达时尽快 trim 当前内部流的执行。这无疑是一个很好的设计决定,否则它会带来很多困惑并允许一些诡异的 Action 。如果你真的想做一些事情 onCancel
你总是可以使用自定义 unsubscribe
回调创建你自己的可观察对象。但我仍然建议不要将 unsubscribe
与外部上下文的状态更改结合起来。理想情况下,unsubscribe
只会清理内部使用的资源。
然而,您的特殊情况可以在不访问 onCancel
或类似方法的情况下得到解决。关键观察是 - 如果我正确理解您的用例 - 在 search
上所有以前/未决的操作可能会被忽略。因此,不用担心递减计数器,我们可以简单地从 1 开始计数。
关于片段的一些评论:
BehaviorSubject
来计算未决请求 - 因为它已准备好与其他流组合;search
仍未决时是否允许 nextPage
- 但似乎只是使用 concatMapTo
的问题vs merge
;Rx
运算符。console.clear();
const searchSub = new Rx.Subject(); // trigger search
const nextPageSub = new Rx.Subject(); // triger nextPage
const pendingSub = new Rx.BehaviorSubject(); // counts number of pending requests
const randDurationFactory = min => max => () => Math.random() * (max - min) + min;
const randDuration = randDurationFactory(250)(750);
const addToPending = n => () => pendingSub.next(pendingSub.value + n);
const inc = addToPending(1);
const dec = addToPending(-1);
const fakeSearch = (x) => Rx.Observable.of(x)
.do(() => console.log(`SEARCH-START: ${x}`))
.flatMap(() =>
Rx.Observable.timer(randDuration())
.do(() => console.log(`SEARCH-SUCCESS: ${x}`)))
const fakeNextPage = (x) => Rx.Observable.of(x)
.do(() => console.log(`NEXT-PAGE-START: ${x}`))
.flatMap(() =>
Rx.Observable.timer(randDuration())
.do(() => console.log(`NEXT-PAGE-SUCCESS: ${x}`)))
// subscribes
searchSub
.do(() => console.warn('NEW_SEARCH'))
.do(() => pendingSub.next(1)) // new search -- ingore current state
.switchMap(
(x) => fakeSearch(x)
.do(dec) // search ended
.concatMapTo(nextPageSub // if you wanted to block nextPage when search still pending
// .merge(nextPageSub // if you wanted to allow nextPage when search still pending
.do(inc) // nexpage started
.flatMap(fakeNextPage) // optionally switchMap
.do(dec) // nextpage ended
)
).subscribe();
pendingSub
.filter(x => x !== undefined) // behavior-value initially not defined
.subscribe(n => console.log('PENDING-REQUESTS', n))
// TEST
const test = () => {
searchSub.next('s1');
nextPageSub.next('p1');
nextPageSub.next('p2');
setTimeout(() => searchSub.next('s2'), 200)
}
// test();
// FUZZY-TEST
const COUNTER_MAX = 50;
const randInterval = randDurationFactory(10)(350);
let counter = 0;
const fuzzyTest = () => {
if (counter % 10 === 0) {
searchSub.next('s' + counter++)
}
nextPageSub.next('p' + counter++);
if (counter < COUNTER_MAX) setTimeout(fuzzyTest, randInterval());
}
fuzzyTest()
<script src="https://npmcdn.com/rxjs@5.0.0-beta.11/bundles/Rx.umd.js"></script>
关于javascript - RxJs flatMapLatest/switchMap 取消回调。 onCancel() 在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39236361/
我不知道这之间是否有区别: Observable.pipe( switchMap((res) => { ... }),
我有以下代码 const mySource:Observable[]> (...) mySource.pipe( switchMap(arr=>forkJoin(arr)); ) 按预期工作,但
我正在尝试将 ViewModel 与某些 LiveData 一起使用,这些 LiveData 使用另一个 LiveData 的值。 为此,我尝试使用 Transformations.switchMap
我有以下组件: @Component({...}) export class AppComponent implements OnInit, OnDestroy { destroy$ = new
以下用例:用户可以加入 0...* 组。每个组都有一个 ID 并包含 0...* 个帖子。 我订阅了一个 Observable(以获取他加入的用户的组)并返回一个字符串数组(组 ID)。 const
我有 3 个端点返回即将发生的、当前的、过去的事件。我应该只显示 future 最远的那个。为了优化调用而不是一次调用所有端点。我编写了一个简单的 RxJs 流,我在其中调用第一个端点,如果它不返回数
我有一个表单,其中有一个按钮,可以使用表单的内容发送电子邮件。我想使用 switchmap,因为我想防止用户垃圾点击并创建大量 HTTP 请求,但我不知道该怎么做。 使用 switchmap 之前:
我正在尝试使用 switchMap 运算符切换可观察值: return this.db.list(`UserPlaces/${this.authData.auth.auth.currentUser.u
我尝试执行以下搜索: 我想根据第一个 id 搜索某些内容,这会返回一个 FirebaseListObservable。然后我尝试在 Observable 的 switchMap 函数中执行代码,因为搜
Observable .interval(2, TimeUnit.SECONDS) .switchMap(integer -> Observable
我遵循了教程 Angular Tour of Heroes 和其他一些教程,现在我正在尝试使用 Angular 2 构建应用程序。基本上,当我们正在监听 Subject 的变化时,我们可以等待几秒钟,
我有一个 Angular 应用程序,它向 Http 服务发出请求并在另一个 Http 服务上调用 switchMap。由于某种原因,switchMap 中的请求仅在第一次调用父调用时运行。否则父请求会
Angular 和 RxJS 的新手,试图稍微了解一下...我的应用程序对 UI 事件使用react,结果调用返回 Observable 的 HTTP 服务。我这样订阅: this.myXYZServ
我想解析一个 observable,但我不希望返回值替换管道中的先前值。有没有异步tap() ?我需要一个像 switchMap 这样的运算符(operator)但我想忽略返回。 of(1).pipe
我有一个 Observable,其中每个新值都应该引起一个 HTTP 请求。在客户端,我只关心最新的响应值;但是,我希望每个请求都能完成以进行监控/等。目的。 我目前拥有的是这样的: function
我有 HTTP 拦截器。在那个拦截器中,在我更改请求之前,我需要打开一个加载程序。 真正让我担心的是,我最终有很多 switchMap s。 为什么? 加载器是异步的 我还需要翻译从拦截器传递到加载器
这个问题已经有答案了: Angular 7 - nesting Observables (1 个回答) 已关闭 4 年前。 我正在尝试按照 Angular Routing 中有关如何获取路由参数的教程
我在使用 ngrx.store 和 states 时遇到了错误(?)。 在我调度新状态并且 reducer 返回新状态之后什么都没有发生。订阅不会收到任何错误消息。如果我删除 switchMap,代码
目前我有这段代码 this.save() .pipe(switchMap(() => this.unlock())) .subscribe(...); save 和unlock 实现是 pri
如果满足条件,我将尝试从 switchmap 返回一个值,但它返回的是拆分为单个字符的 console.log。因此,如果 Angular 色以 Buyer 身份返回,则它以 身份返回 console
我是一名优秀的程序员,十分优秀!