我正在进行异步调用,10秒后持续1分钟意味着将进行大约6次调用,但问题在于我希望它在特定delay
上应用condition
Observable
.just(listOfSomethings_Locally)
.take(1, TimeUnit.MINUTES)
.serialize()
.delaySubscription( // this is confusing part
() ->
Observable.just(listOfItems_Network).take(10,TimeUnit.SECONDS)
)
我想要的是将网络通话延迟10秒(第一次通话除外),并在10秒后取消网络通话,所以我应该在1分钟内完成6次通话。
修改
由于场景混乱,这里重新定义了场景:
我拥有的是当地的大量驱动程序,我想发送 每隔10秒钟向每个人请求并听取另一个 订户检查司机是否在10秒内没有取消, 这个过程将持续大约1分钟,如果一个司机取消我应该 立即向下一个发送请求
到目前为止编写的代码:
Observable.from(driversGot)
.take(1,TimeUnit.MINUTES)
.serialize()
.map(this::requestRydeObservable) // requesting for single driver from driversGot (it's a network call)
.flatMap(dif ->
Observable.amb(
kh.getFCM().driverCanceledRyde(), // listen for if driver cancel request returns integer
kh.getFCM().userRydeAccepted()) // listen for driver accept returns RydeAccepted object
.map(o -> {
if (o instanceof Integer) {
return new RydeAccepted();
} else if (o instanceof RydeAccepted) {
return (RydeAccepted) o;
}
return null;
}).delaySubscription(10,TimeUnit.SECONDS)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(fua -> {
if (fua == null) {
UiHelpers.showToast(context, "Invalid Firebase response");
} else if (!fua.getStatus()) { // ryde is canceled because object is empty
UiHelpers.showToast(context, "User canceled ryde");
} else { // ryde is accepted
UiHelpers.showToast(context, "User accepted ryde");
}
}, t -> {
t.printStackTrace();
UiHelpers.showToast(context,"Error sending driver requests");
}, UiHelpers::stopLoading);
答案 0 :(得分:2)
您不需要take
和serialize
因为just
会立即+连续发出内容。
delaySubscription
似乎是一个奇怪的选择,因为在传递的observable生成事件后,其他事件不会延迟(这与您的情况相矛盾)
使用delay
+计算其余事件的个别延迟(因此第一个延迟0秒,第二个延迟1秒,第三个延迟3个,......)
AtomicLong counter = new AtomicLong(0);
System.out.println(new Date());
Observable.just("1", "2", "3", "4", "5", "6")
.delay(item -> Observable.just(item).delay(counter.getAndIncrement(), TimeUnit.SECONDS))
.subscribe(new Consumer<String>() {
public void accept(String result) throws Exception {
System.out.println(result + " " + new Date());
}
});
System.in.read();
看起来你的用例适合速率限制,所以我们可以使用guava的RateLimiter:
RateLimiter limiter = RateLimiter.create(1);
System.out.println(new Date());
Observable.just("1", "2", "3", "4", "5", "6")
.map(r -> {
limiter.acquire();
return r;
})
.subscribe(new Consumer<String>() {
public void accept(String result) throws Exception {
System.out.println(result + " " + new Date());
}
});
System.in.read();
两者的工作方式相似:
Tue Nov 15 11:14:34 EET 2016
1 Tue Nov 15 11:14:34 EET 2016
2 Tue Nov 15 11:14:35 EET 2016
3 Tue Nov 15 11:14:36 EET 2016
4 Tue Nov 15 11:14:37 EET 2016
5 Tue Nov 15 11:14:38 EET 2016
6 Tue Nov 15 11:14:39 EET 2016
如果您的请求,速率限制器可以更好地工作,例如交接5秒,然后它将允许下一个请求更快地补偿延迟并达到1req / s的目标10秒。
答案 1 :(得分:0)
你好,你可以延迟使用重试有一种方法可以做到here
答案 2 :(得分:0)
我想更新@Ivans帖子,因为它缺少错误处理并且正在使用副作用。
这篇文章只会使用RxJava-operators。可观察量将每10秒提供一个值。请求将在10秒内超时。如果它达到超时,将返回一个回退值。
第一个测试方法将在60秒内收到10个值。如果最后一个请求在10秒之前完成,则观察者可以在60秒之前完成。
public class TimeOutTest {
private static String DUMMY_VALUE = "ERROR";
@Test
public void handles_in_60_seconds() throws Exception {
List<Integer> actions = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Observable<Long> timer = Observable.interval(0, 10, TimeUnit.SECONDS).take(6);
Observable<Integer> vales = Observable.fromIterable(actions)
.take(6);
Observable<Integer> observable = Observable.zip(timer, vales, (time, result) -> {
return result;
});
Observable<String> stringObservable = observable.flatMap(integer -> {
return longNetworkLong(9_000)
.timeout(10, TimeUnit.SECONDS)
.onErrorReturnItem(DUMMY_VALUE);
}).doOnNext(s -> System.out.println("VALUE"));
stringObservable.test()
.awaitDone(60, TimeUnit.SECONDS)
.assertValueCount(6);
}
@Test
public void last_two_values_timeOut() throws Exception {
List<Integer> actions = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Observable<Long> timer = Observable.interval(0, 10, TimeUnit.SECONDS).take(6);
Observable<Integer> vales = Observable.fromIterable(actions)
.take(6);
Observable<Integer> observable = Observable.zip(timer, vales, (time, result) -> {
return result;
});
Observable<String> stringObservable = observable
.map(integer -> integer * 2500)
.flatMap(integer -> {
return longNetworkLong(integer)
.timeout(10, TimeUnit.SECONDS)
.doOnError(throwable -> System.out.print("Timeout hit?"))
.onErrorReturnItem(DUMMY_VALUE);
})
.doOnNext(s -> System.out.println("VALUE"))
.filter(s -> !Objects.equals(s, DUMMY_VALUE));
stringObservable.test()
.awaitDone(60, TimeUnit.SECONDS)
.assertValueCount(4);
}
private Observable<String> longNetworkLong(int delayTime) {
return Observable.fromCallable(() -> {
Thread.sleep(delayTime);
return "result";
});
}
}