我目前正试图点击服务并返回一个对象列表,在它返回给订阅者之前,我想对列表中的每个对象进行另一个同步调用,以进行另一个服务调用来设置缺少一个领域。我成功完成了所有调用,但订阅者返回的对象有这个字段我需要设置为null。以下是我的代码示例:
示例服务:
rx.Observable<List<ExampleObject>> getExampleObject();
rx.Observable<MissingObject> getMissingObjectByFoo(@Path("foo") String foo);
示例类:
public class ExampleObject {
String foo;
MissingObject bar;
public String getFoo() {
return this.foo;
}
public void setFoo(String value) {
this.foo = value;
}
public MissingObject getBar() {
return this.bar;
}
public void setBar(MissingObject value) {
this.bar = value;
}
}
示例实施:
mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<?>>() {
@Override
public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
for (ExampleObject entry : exampleObjects) {
String foo = entry.getFoo();
mService.getMissingObjectByFoo(foo)
.subscribeOn(mScheduler.backgroundThread())
.observeOn(mScheduler.mainThread())
.subscribe(new Subscriber<MissingObject>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(MissingObject missingObject) {
entry.setBar(missingObject);
}
});
}
return Observable.just(exampleObjects);
};
答案 0 :(得分:4)
由于您更新条目的中间调用是异步的,我不认为您可以坚持使用return Post::where('user_id', Auth::user()->id)->withCount(['visitors' => function($query)
{
$query->where('created_at', '<=', Carbon\Carbon::now())->where('created_at', '>=', Carbon\Carbon::yesterday());
}])->get()->sum('visitors_count');
,而应直接从List<ExampleObject>
操纵ExampleObject
:
Observable
旁注:
如果您可以使用mService.getExampleObject()
// Spread the list
.flatMap(list -> Observable.from(list))
// Update your object
// Here we zip the object with the missing object,
// so that when the missing object is obtained,
// we update the entry and emit it.
.flatMap(entry -> Observable.zip(
Observable.just(entry),
mDocsService.getMissingObjectByFoo(entry.getFoo()),
(entry, missingObject) -> {
entry.setBar(missingObject);
return entry;
})
)
// if you really want a map after all
.toList();
中的函数取决于外部变量(条目),则可以跳过该zip。这是我试图避免的事情,但无论如何它都在这里:
map
答案 1 :(得分:3)
您正在寻找zip
运算符,如下所述:Zip Operator。我想你想把你的所有电话都拉到一个拉链,所以,就像这样:
mService.getExampleObject().flatMap(new Func1<List<ExampleObject>, Observable<ExampleObject>>() {
@Override
public Observable<List<ExampleObject>> call(List<ExampleObject> exampleObjects) {
List<Observable<ExampleObject>> allTheObservables = new ArrayList<Observable<ExampleObject>>();
for (ExampleObject entry : exampleObjects) {
allTheObservables.add(mService.getMissingObjectByFoo(foo).map(new Func1<MissingObject, ExampleObject>() {
@Override
public ExampleObject call(MissingObject missingObject) {
return entry.setBar(missingObject);
}
}));
}
return Observable.zip(allTheObservables, new FuncN<ExampleObject>() {
@Override
public ExampleObject call(ExampleObject... args) {
return Arrays.asList(args);
}
});
}
});
如果不起作用,或者存在语法问题,这是一个具体的例子,使用github api:
service.getContributorsObservable("square", "dagger")
.flatMap(new Func1<List<Contributor>, Observable<List<String>>>() {
@Override
public Observable<List<String>> call(List<Contributor> contributors) {
List<Observable<String>> allTheObservables = new ArrayList<>(contributors.size());
for (final Contributor contributor : contributors) {
allTheObservables.add(service.getContributorsObservable(contributor.login).map(new Func1<User, String>() {
@Override
public String call(User user) {
return contributor.login + " is " + user.name;
}
}));
}
return Observable.zip(allTheObservables, new FuncN<List<String>>() {
@Override
public List<String> call(Object... args) {
return Arrays.asList((String[]) args);
}
});
}
});
请注意,这将进行n + 1个网络呼叫,1个用于ExampleObject
的列表,然后在该列表中每ExampleObject
个1个。如果可能,我强烈建议您与API的维护者交谈,以便在API端获取信息查找。只知道这将使用一些带宽!