How to compose Observables to avoid the given nested and dependent callbacks?

后端 未结 2 1501
盖世英雄少女心
盖世英雄少女心 2020-12-04 20:23

In this blog, he gives this (copy/pasted the following code) example for the callback hell. However, there is no mention of how the issue can be eliminated by using Reactive

相关标签:
2条回答
  • 2020-12-04 20:40

    According to your code. Suppose that the remote call are done using Observable.

     Observable<Integer>  callRemoveServiceA()  { /* async call */  }
    
    /* .... */
    
    Observable<Integer>  callRemoveServiceE(Integer f2) { /* async call */  }
    

    What you want :

    • call serviceA then call serviceB with the result of serviceA
    • call serviceC then call serviceD and serviceE with the result of serviceC
    • with the result of serviceE and serviceD, build a new value
    • display the new value with the result of serviceB

    With RxJava, you'll achieve this with this code :

    Observable<Integer> f3 = callRemoveServiceA() // call serviceA
                // call serviceB with the result of serviceA
                .flatMap((f1) -> callRemoveServiceB(f1)); 
    
    
    Observable<Integer> f4Andf5 = callRemoveServiceC() // call serviceC
                        // call serviceD and serviceE then build a new value
                        .flatMap((f2) -> callRemoveServiceD(f2).zipWith(callRemoveServiceE(f2), (f4, f5) -> f4 * f5));
    
    // compute the string to display from f3, and the f4, f5 pair
    f3.zipWith(f4Andf5, (childF3, childF4Andf5) -> childF3 + " => " + childF4Andf5)
                // display the value
                .subscribe(System.out::println);
    

    the important part here is the use of flapMap and zip (or zipWith)

    • flapMap will transform a value into another Observable. This Observable here will be your new asynchronos call. ( http://reactivex.io/documentation/operators/flatmap.html )
    • zip will compose a new value from two different Observable. So you can build a new value with the result of two (or more) Obsevable ( http://reactivex.io/documentation/operators/zip.html )

    You can get more info on flapMap here : When do you use map vs flatMap in RxJava?

    0 讨论(0)
  • 2020-12-04 20:57

    I'm the original author of the referenced blog post about callbacks and Java Futures. Here is an example of using flatMap, zip and merge to do service composition asynchronously.

    It fetches a User object, then concurrently fetches Social and PersonalizedCatalog data, then for each Video from the PersonalizedCatalog concurrently fetches a Bookmark, Rating and Metadata, zips those together, and merges all of the responses into a progressive stream output as Server-Sent Events.

    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");
    });
    

    This example can be seen in context of a functioning application at https://github.com/Netflix/ReactiveLab/blob/952362b89a4d4115ae0eecf0e73f273ecb27ba98/reactive-lab-gateway/src/main/java/io/reactivex/lab/gateway/routes/RouteForDeviceHome.java#L33

    Since I can't possibly provide all of the information here you can also find an explanation in presentation form (with link to video) at https://speakerdeck.com/benjchristensen/reactive-streams-with-rx-at-javaone-2014?slide=32.

    0 讨论(0)
提交回复
热议问题