0

Is there a more practical way to nest these observables with RX/JS. Here is a snippet, where I am storing an image first, then returning the download URL and placing it in the real time database.

return new Observable(observer => {
        firebase.storage().ref().child('users/' + this.userService.getUserID() + '/messages/').put(image).then((data) => {

          updates['photoURL'] = data.downloadURL;

          firebase.database().ref().update(updates).then(() => {
            observer.next();
            observer.complete();
          }).catch((error) => {
            observer.error(error);
          })
        }, (error) => {
          observer.error(error);
        })
      });
Jay Ordway
  • 1,708
  • 2
  • 11
  • 33

1 Answers1

1

You can use higher-order Observables and their respective operators to inline operations which depend on each other. For instance:

function uploadImageAndUpdateState(userId, image, updates) {
  return Observable.defer(() => firebase.storage().ref().child(`users/${userId}/messages/`).put(image))
    .mergeMap(imagePutData => {
      updates['photoURL'] = imagePutData.downloadURL;
      return firebase.database().ref().update(updates;
    });
});

By using Defer() on the image put (promise) this Observable will start after subscribing to uploadImageAndUpdateState to upload the image, after receiving data from that operation modify the updates and update that as well in firebase. Since your example contained no error handling (only propagation) this is not done in this function, you still need to handle that yourself in your subscribe(.., onError => ???) logic.

Mark van Straten
  • 9,287
  • 3
  • 38
  • 57
  • Is there a potential downside or unwanted behavior from the code the way it is in the snippet? – Jay Ordway Sep 05 '17 at 09:40
  • Downsides of the code per the questions snippet: no cancellation support, bit messy & superfluous due to the use of low-abstraction methods (`new Observable` // `Observable.create()` vs `Observable.from()` // `Observable.defer()` // ... – Mark van Straten Sep 05 '17 at 13:18
  • If it is just a singular call to firebase, are the low methods acceptable such as within this tutorial? http://masteringionic.com/blog/2017-03-06-uploading-images-to-firebase-storage-with-ionic-part-2/ – Jay Ordway Sep 05 '17 at 13:23
  • Even though `Observable.create` [just wraps `new Observable()`](http://reactivex.io/rxjs/file/es6/MiscJSDoc.js.html#lineNumber129) the former is preferred. But that is just syntax. It will work. As stated in my previous comment; you are not gaining all the benefits you could get from Observables if you should use more suitable functions to compose the behaviour you search. – Mark van Straten Sep 05 '17 at 15:12
  • Are there any patterns to follow when nesting three firebase calls or N api calls for a more general case? – Jay Ordway Sep 06 '17 at 06:38