Skip to content

Instantly share code, notes, and snippets.

@daviddefco
Last active April 4, 2017 15:29
Show Gist options
  • Save daviddefco/9ffcc8075c511b888cd2f4c1209e02ca to your computer and use it in GitHub Desktop.
Save daviddefco/9ffcc8075c511b888cd2f4c1209e02ca to your computer and use it in GitHub Desktop.
Typescript examples working with Observables (React) in asynchronous computing

Handling Asynchronous Code with Observables

Packaging Asynchronous Requests to Extract More Details

There are situations where we make an asynchronous request to get a list of entities (albums in the example). For each album we need to send another asynchronous request to get more detail about the entity, so that we can transofrm the entity with more detailed data. From the design point of view the cleanes solution is to hold all the logic needed for that process in a service, and the controller will ideally subscribe to a single observer that delivers the enriched entity (the original entity+ further details for the second data request).

We have two levels: the outer level gets the list of albums and tranform the list of albums in another Observable. For each emission of this Observable we are going to zip (to package) the album as observable (with a unique emission: the album), and another observable that makes the detailed information request. In the transformation of this zipped Observable detailed data is added to the information retrieved for the album.

getAlbums(): Observable<Album> {
    return this._http.get(this.urlRestfulApi + '/album')   
    // flats the array of one observable to a single observable
    .flatMap(albumList =>
      Observable.from(albumList.json().albums)
      // flats the array of one observable for each album in an array
      // of a single observable
      .flatMap(response => {
        let album = response as Album
        // Combine one observable for each album with the observable to 
        // get the portrait of the album
        return Observable.zip (
          Observable.of(album),
          this.getFirstImage(album._id),
          (album, uri) => {
            // Tranforms the album object adding the uri of the portrait,
            // extracted for the second observable
            album.portraitUrl = uri
            return album
          }
        )
      })
    )     
  }
  
 getFirstImage(idAlbum: string) : Observable<string> {
    // If we use map we get an array of Observables with only one
    // observable, while what we want is a unique observable with
    // the emission of one object (the firt photo)
    return this._http.get(this.urlRestfulApi + `/image/album/${ idAlbum }`)
    .flatMap(imagesList => {
      return Observable.from(imagesList.json().images)
        // get the first image associated with the album, we ignore rest fo images
        .take(1)
        .map(result => {
          let image = result as Image
          // Return the uri instead the whole image
          return this.urlRestfulApi + `/image-file/${ image._id }`
        })        
    })
  }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment