gpt4 book ai didi

java - 如何组合 Observables 以避免给定的嵌套和依赖回调?

转载 作者:IT老高 更新时间:2023-10-28 20:51:17 25 4
gpt4 key购买 nike

this blog ,他给this (复制/粘贴以下代码)回调 hell 的示例。但是,没有提到如何通过使用 Reactive Extensions 来消除该问题。

所以这里 F3 取决于 F1 完成,而 F4 和 F5 取决于 F2 完成。

  1. 想知道 Rx 中的等效功能是什么。
  2. 如何在Rx中表示F1、F2、F3、F4、F5都要异步拉取?

注意:我目前正试图围绕 Rx 进行思考,所以在问这个问题之前我没有尝试解决这个例子。

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

public class CallbackB {

/**
* Demonstration of nested callbacks which then need to composes their responses together.
* <p>
* Various different approaches for composition can be done but eventually they end up relying upon
* synchronization techniques such as the CountDownLatch used here or converge on callback design
* changes similar to <a href="https://github.com/Netflix/RxJava">Rx</a>.
*/
public static void run() throws Exception {
final ExecutorService executor = new ThreadPoolExecutor(4, 4, 1, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>());
/* the following are used to synchronize and compose the asynchronous callbacks */
final CountDownLatch latch = new CountDownLatch(3);
final AtomicReference<String> f3Value = new AtomicReference<String>();
final AtomicReference<Integer> f4Value = new AtomicReference<Integer>();
final AtomicReference<Integer> f5Value = new AtomicReference<Integer>();

try {
// get f3 with dependent result from f1
executor.execute(new CallToRemoteServiceA(new Callback<String>() {

@Override
public void call(String f1) {
executor.execute(new CallToRemoteServiceC(new Callback<String>() {

@Override
public void call(String f3) {
// we have f1 and f3 now need to compose with others
System.out.println("intermediate callback: " + f3 + " => " + ("f4 * f5"));
// set to thread-safe variable accessible by external scope
f3Value.set(f3);
latch.countDown();
}

}, f1));
}

}));

// get f4/f5 after dependency f2 completes
executor.execute(new CallToRemoteServiceB(new Callback<Integer>() {

@Override
public void call(Integer f2) {
executor.execute(new CallToRemoteServiceD(new Callback<Integer>() {

@Override
public void call(Integer f4) {
// we have f2 and f4 now need to compose with others
System.out.println("intermediate callback: f3" + " => " + (f4 + " * f5"));
// set to thread-safe variable accessible by external scope
f4Value.set(f4);
latch.countDown();
}

}, f2));
executor.execute(new CallToRemoteServiceE(new Callback<Integer>() {

@Override
public void call(Integer f5) {
// we have f2 and f5 now need to compose with others
System.out.println("intermediate callback: f3" + " => " + ("f4 * " + f5));
// set to thread-safe variable accessible by external scope
f5Value.set(f5);
latch.countDown();
}

}, f2));
}

}));

/* we must wait for all callbacks to complete */
latch.await();
System.out.println(f3Value.get() + " => " + (f4Value.get() * f5Value.get()));
} finally {
executor.shutdownNow();
}
}

public static void main(String[] args) {
try {
run();
} catch (Exception e) {
e.printStackTrace();
}
}

private static final class CallToRemoteServiceA implements Runnable {

private final Callback<String> callback;

private CallToRemoteServiceA(Callback<String> callback) {
this.callback = callback;
}

@Override
public void run() {
// simulate fetching data from remote service
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.call("responseA");
}
}

private static final class CallToRemoteServiceB implements Runnable {

private final Callback<Integer> callback;

private CallToRemoteServiceB(Callback<Integer> callback) {
this.callback = callback;
}

@Override
public void run() {
// simulate fetching data from remote service
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.call(100);
}
}

private static final class CallToRemoteServiceC implements Runnable {

private final Callback<String> callback;
private final String dependencyFromA;

private CallToRemoteServiceC(Callback<String> callback, String dependencyFromA) {
this.callback = callback;
this.dependencyFromA = dependencyFromA;
}

@Override
public void run() {
// simulate fetching data from remote service
try {
Thread.sleep(60);
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.call("responseB_" + dependencyFromA);
}
}

private static final class CallToRemoteServiceD implements Runnable {

private final Callback<Integer> callback;
private final Integer dependencyFromB;

private CallToRemoteServiceD(Callback<Integer> callback, Integer dependencyFromB) {
this.callback = callback;
this.dependencyFromB = dependencyFromB;
}

@Override
public void run() {
// simulate fetching data from remote service
try {
Thread.sleep(140);
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.call(40 + dependencyFromB);
}
}

private static final class CallToRemoteServiceE implements Runnable {

private final Callback<Integer> callback;
private final Integer dependencyFromB;

private CallToRemoteServiceE(Callback<Integer> callback, Integer dependencyFromB) {
this.callback = callback;
this.dependencyFromB = dependencyFromB;
}

@Override
public void run() {
// simulate fetching data from remote service
try {
Thread.sleep(55);
} catch (InterruptedException e) {
e.printStackTrace();
}
callback.call(5000 + dependencyFromB);
}
}

private static interface Callback<T> {
public void call(T value);
}
}

最佳答案

我是有关回调和 Java future 的引用博客文章的原作者。这是一个使用 flatMap、zip 和 merge 异步进行服务组合的示例。

它获取一个 User 对象,然后同时获取 Social 和 PersonalizedCatalog 数据,然后为 PersonalizedCatalog 中的每个视频同时获取一个书签、评级和元数据,将它们压缩在一起,并将所有响应合并到一个渐进式流输出中作为服务器- 发送事件。

return getUser(userId).flatMap(user -> {
Observable<Map<String, Object>> catalog = getPersonalizedCatalog(user)
.flatMap(catalogList -> catalogList.videos().<Map<String, Object>> flatMap(
video -> {
Observable<Bookmark> bookmark = getBookmark(video);
Observable<Rating> rating = getRatings(video);
Observable<VideoMetadata> metadata = getVideoMetadata(video);
return Observable.zip(bookmark, rating, metadata, (b, r, m) -> combineVideoData(video, b, r, m));
}));

Observable<Map<String, Object>> social = getSocial(user).map(s -> {
return s.getDataAsMap();
});

return Observable.merge(catalog, social);
}).flatMap(data -> {
String json = SimpleJson.mapToJson(data);
return response.writeStringAndFlush("data: " + json + "\n");
});

这个例子可以在 https://github.com/Netflix/ReactiveLab/blob/952362b89a4d4115ae0eecf0e73f273ecb27ba98/reactive-lab-gateway/src/main/java/io/reactivex/lab/gateway/routes/RouteForDeviceHome.java#L33 的一个正常运行的应用程序的上下文中看到。

由于我无法在此处提供所有信息,您还可以在 https://speakerdeck.com/benjchristensen/reactive-streams-with-rx-at-javaone-2014?slide=32 以演示文稿形式(带有视频链接)找到解释。 .

关于java - 如何组合 Observables 以避免给定的嵌套和依赖回调?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28402376/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com