Search code examples
angularrxjsobservableswitchmap

switchmap complains not returning but thought i was


here is the error:

ERROR TypeError: You provided 'undefined' where a stream was expected. You can provide an Observable, Promise, Array, or Iterable.

Here is the code

publicresourceuploadtos3(event): Observable<any>{
    console.log('it got inside the public resource upload to s3 ');
    const mediatobeuploaded = event.target.files[0];
    return this.http.get(environment.public_generate_presigned_url_resource).pipe(
      switchMap((req : any)=>{
        const resourceurlprovided = req.uriroot + req.fields.key;
        console.log('it got the public presigned url');

        let fd = new FormData();
        fd.append('acl', req.fields.acl);
        fd.append('key', req.fields.key);
        fd.append('content-type', req.fields['content-type']);
        fd.append('policy', req.fields.policy);
        fd.append('x-amz-algorithm', req.fields['x-amz-algorithm']);
        fd.append('x-amz-credential', req.fields['x-amz-credential']);
        fd.append('x-amz-date', req.fields['x-amz-date']);
        fd.append('x-amz-signature', req.fields['x-amz-signature']);

        fd.append('file', mediatobeuploaded);
        return this.http.post(req.url, fd, {
         reportProgress: true,
         observe: 'events'
       }).pipe(
         // answer two https://stackoverflow.com/questions/51176537/angular-6-and-node-js-aws-s3-file-upload-progress-bar
         switchMap((events: any)=>{
           console.log('it got into the swtich map');
           switch(events.type){
             case HttpEventType.UploadProgress:
               const result = {
                 progressreport: true,
                 progress: Math.round(events.loaded / events.total * 100)
               };
               console.log('it went into upload progress');
               return of(result);
             case HttpEventType.Response:
               const result2 = {
                 progressreport: false,
                 resourceurl: resourceurlprovided,
                 resourcekey: req.fields.key
               };
               console.log('it went into the response');
               return of(result2);
           }
         }));

      }));
  }

notice the console.log() statements. The last one to fire is console.log('it got into the switch map')

which means my switch map is calling this error because it expects to return observables.

but look at this code.

switch(events.type){
             case HttpEventType.UploadProgress:
               const result = {
                 progressreport: true,
                 progress: Math.round(events.loaded / events.total * 100)
               };
               console.log('it went into upload progress');
               return of(result);
             case HttpEventType.Response:
               const result2 = {
                 progressreport: false,
                 resourceurl: resourceurlprovided,
                 resourcekey: req.fields.key
               };
               console.log('it went into the response');
               return of(result2);
           }
         }));

what of the return of statements why don't those satisfy? What am i doing wrong? My understanding is that the return of is an observable.

Part of my thought process is that I need to have a default of statment if the two switch case statements don't work. But I tried that and my IDE kept yelling at me. So either Im doing something completely silly, or I am missing something important.


Solution

    1. If you're returning of(result) inside a switchMap(), then use map() instead. You can simply return the result without wrapping it in of().
    2. Your switch block handles two cases, but what if both cases fail? That is when you are not returning anything. Try adding a default case at the end to return something if both cases fail.