Arash
Arash

Reputation: 12425

return an observable from a finalize method on observable

Concrete case is this: AngularFirebase documentation says that in order to get the download URL from an uploaded file, you need to do this:

const task = this.storage.upload(filePath, file);

// observe percentage changes
// get notified when the download URL is available
task.snapshotChanges().pipe(
    finalize(() => this.downloadURL = fileRef.getDownloadURL() )
 )
.subscribe();
}

Now, I have an upload method and I want to return from it, an observable of string. My method signature looks like :

upload(file :File) :Observable<string> {

......

}

I tried doing this :

return <Observable<string>>task.snapshotChanges().pipe(
        finalize(() => {
            const url = fileRef.getDownloadURL();
            console.log('download url is ',url);
            return url;
        })
    );

But this doesn't work because, there are other elements of type snapshot changes in the original observable.

Now my question is, how I can use the code in the example to effectively return the type I want

Upvotes: 4

Views: 2730

Answers (2)

nganltt
nganltt

Reputation: 1

I have the same issue and here is my solution

return <Observable<string>>task
      .snapshotChanges()
      .pipe(
        last(),
        flatMap(
          () => {
            return fileRef.getDownloadURL().pipe(
              map((url) => {
                return url;
              })
            );
          }
        )
      );

Upvotes: 0

ggradnig
ggradnig

Reputation: 14179

As stated in the documentation, finalize...

Returns an Observable that mirrors the source Observable, but will call a specified function when the source terminates on complete or error.

That means, you cannot alter the Observable type with the passed function.

Instead, you can combine the last operator and the map operator to get a notification for the last value, mapped to the desired property. It would look like this:

return <Observable<string>>task.snapshotChanges().pipe(
        last(),
        map(() => {
            const url = fileRef.getDownloadURL();
            console.log('download url is ',url);
            return url;
        })
    );

Upvotes: 5

Related Questions