我试图并行加载用户对象。
final User user = new User();
final Observable<User> userObs = Observable.just("NAMES", "ADDRESSES", "CURRENT_ADDRESS")
.flatMap(field -> getOrchestrator(user, field))
.scan(new User(), (finalUser, event) -> {
finalUser = event;
return finalUser;
});
扫描确实会发出三个用户对象,因为reduce根本不会发出任何项目?我在这做错了什么。
final User user = new User();
final Observable<User> userObs = Observable.just("NAMES", "ADDRESSES", "CURRENT_ADDRESS")
.flatMap(field -> getOrchestrator(user, field))
.reduce(new User(), (finalUser, event) -> {
finalUser = event;
return finalUser;
});
getOrchestrator返回Observable。任何帮助将不胜感激。
以下是完整的代码段
public class Orchestrator {
private String userId;
public Orchestrator(final String userId) {
this.userId = userId;
}
public static void main(final String[] args) throws Exception {
final User user = new User();
final Observable<User> userObs = Observable.just("NAMES", "ADDRESSES", "CURRENT_ADDRESS")
.flatMap(field -> getOrchestrator(user, field))
.scan(new User(), (finalUser, event) -> {
finalUser = event;
return finalUser;
});
userObs.subscribeOn(Schedulers.io()).subscribe(result -> {
System.out.println(result.toString());
});
TimeUnit.SECONDS.sleep(10);
}
private static Observable<User> getOrchestrator(final User user, final String fieldName) {
switch (fieldName) {
case "CURRENT_ADDRESS":
return new AddressOrchestrator().getCurrentAddress(user.getUserId())
.map(currentAddress -> {
user.setAddress(currentAddress);
try {
TimeUnit.MILLISECONDS.sleep(200);
}
catch (final InterruptedException e) {
}
return user;
});
case "ADDRESSES":
return new AddressOrchestrator().getAddresses(user.getUserId())
.map(addresses -> {
user.setAddresses(addresses);
try {
TimeUnit.MILLISECONDS.sleep(200);
}
catch (final InterruptedException e) {
}
return user;
});
case "NAMES":
return new NameOrchestrator().getNames(user.getUserId())
.map(names -> {
user.setNames(names);
try {
TimeUnit.MILLISECONDS.sleep(200);
}
catch (final InterruptedException e) {
}
return user;
});
}
return null;
}
public User getUser() {
final Random r = new Random();
if (r.nextInt(3) % 2 == 0) {
return new User();
}
throw new RuntimeException();
}
}
每个orchestrator都返回Observable。
public class AddressOrchestrator {
public Observable<List<Address>> getAddresses(final String userId) {
return Observable.create(s -> {
final Address currentAddress = this.getBaseAddress(userId);
final Address anotherAddress = this.getBaseAddress(userId);
anotherAddress.setState("NE");
s.onNext(Arrays.asList(currentAddress, anotherAddress));
});
}
public Observable<Address> getCurrentAddress(final String userId) {
return Observable.create(s -> s.onNext(this.getBaseAddress(userId)));
}
public Address getBaseAddress(final String userId) {
final Address address = new Address();
address.setLine1("540 Caddo Lake Dr");
address.setCity("Georgetown");
address.setCountry("USA");
address.setState("TX");
return address;
}
}
public class NameOrchestrator {
public Observable<List<Name>> getNames(final String userId) {
return Observable.create(s -> {
final Name name = new Name();
name.setName("Vanchi");
final Name formerName = new Name();
formerName.setName("Vanchinathan");
s.onNext(Arrays.asList(name, formerName));
});
}
}
答案 0 :(得分:3)
您使用Observable.create
创建的编排(除非您真正知道自己正在做什么,否则一个大红旗)不会终止。这会导致无限的流(从某种意义上说,永远不会发出完整的事件)。你需要什么呢
public Observable<List<Address>> getAddresses(final String userId) {
return Observable.create(s -> {
final Address currentAddress = this.getBaseAddress(userId);
final Address anotherAddress = this.getBaseAddress(userId);
anotherAddress.setState("NE");
s.onNext(Arrays.asList(currentAddress, anotherAddress));
s.onCompleted();
});
注意被调用的onCompleted
。这将解决您的表面问题,但您最好先摆脱Observable.create
并使用Observable.defer
之类的东西。
答案 1 :(得分:1)
这种情况正在发生,因为scan
会发出所有上游项,而reduce
只会在流完成后才会发出。
替换
public Observable<Address> getCurrentAddress(final String userId) {
return Observable.create(s -> s.onNext(this.getBaseAddress(userId)));
}
带
public Observable<Address> getCurrentAddress(final String userId) {
return Observable.fromCallable(() -> this.getBaseAddress(userId));
}
和
public Observable<List<Address>> getAddresses(final String userId) {
return Observable.create(s -> {
final Address currentAddress = this.getBaseAddress(userId);
final Address anotherAddress = this.getBaseAddress(userId);
anotherAddress.setState("NE");
s.onNext(Arrays.asList(currentAddress, anotherAddress));
});
}
与
public Observable<List<Address>> getAddresses(final String userId) {
return Observable.fromCallable(() -> this.getBaseAddress(userId))
.zipWith(Observable.fromCallable(() -> this.getBaseAddress(userId))
.map(address -> address.setState("NE")),
(currentAddress, anotherAddress) -> Arrays.asList(currentAddress, anotherAddress));
}
并将您的setAddress()
方法更改为此
public Address setState(String state) {
this.state = state;
return this;
}
fromCallable()
是创建最多只发出一个元素的Observable
的更好方法,因为它会为您处理错误和背压。