0

This is quite confusing. I'm using angular(ionic) and calling two chain promises then would like to return as observable as below. I've tried adding return in front of two promises but of course throws compile error.

Type 'Promise<Observable<{ formInstanceId: any; questionId: any; repeatId: any; filename: any; isEquipment: any; }>>' is not assignable to type 'Observable<any>'.   Property '_isScalar' is missing in type 'Promise<Observable<{ formInstanceId: any; questionId: any; repeatId: any; filename: any; isEquipment: any; }>>'

I thought about use from(promise1) and from(promise2) but then it got even more confusing..

Main reason I want to change this to full observable because I want to use timeout() in the post() at the end of the code below

public uploadFile(formInstanceId, questionId, repeatId, filePath, isEquipment): Observable<any> {

    this._file.resolveLocalFilesystemUrl(filePath).then(result => {
    console.log("fileSelected", result);

    let fileName = result.name;
    let nativeURL = result.nativeURL;
    let path = nativeURL.substring(0, nativeURL.lastIndexOf("/"));

    this._file.readAsArrayBuffer(path, fileName).then(buffer => {
      let imgBlob = new Blob([buffer], {type: "image/jpeg"});

      let params = {fileName: 'attachment'};
      let query = this.encodeQueryData(params);

      let uploadFileURL = this._networkService.serverUrl + '/api/upload?' + query;


      return this._networkService.postFile(uploadFileURL, fileName, imgBlob).pipe(map(response => {
          console.log(response);
          return {
            formInstanceId: formInstanceId,
            questionId: questionId,
            repeatId: repeatId,
            filename: response[0].filepath,
            isEquipment: isEquipment
          };
        },
        error => {
          return throwError(error);
        }
      ));


    });
  })

}

1 Answers1

0

You can use from operator from RxJs which will convert any Promise to Observable and chain it further (possibly using flatMap). Refer: https://www.learnrxjs.io/operators/creation/from.html

Similar questions answered here:

Return Observable inside the Promise

How to return Observable after some Promise get resolved in Ionic 2/Angular 2? (fromPromise operator mentioned here should be replaced with the new from operator)

Another option is to use async await keywords in Typesript/ES6. Wherever you call uploadFile method, just use (await uploadFile(formInstanceId, questionId, repeatId, filePath, isEquipment)) which will return an observable which was returned by networkService.postFile() method.

Your method will become:

 public async uploadFile(formInstanceId, questionId, repeatId, filePath, isEquipment): Promise<Observable<any>> {

    const result = await this._file.resolveLocalFilesystemUrl(filePath);
    console.log("fileSelected", result);

    let fileName = result.name;
    let nativeURL = result.nativeURL;
    let path = nativeURL.substring(0, nativeURL.lastIndexOf("/"));

    const buffer = await this._file.readAsArrayBuffer(path, fileName);
    let imgBlob = new Blob([buffer], {type: "image/jpeg"});

    let params = {fileName: 'attachment'};
    let query = this.encodeQueryData(params);

    let uploadFileURL = this._networkService.serverUrl + '/api/upload?' + query;

    return this._networkService.postFile(uploadFileURL, fileName, imgBlob).pipe(map(response => {
        console.log(response);
        return {
        formInstanceId: formInstanceId,
        questionId: questionId,
        repeatId: repeatId,
        filename: response[0].filepath,
        isEquipment: isEquipment
        };
    },
    error => {
        return throwError(error);
    }
    ));
}

Here is how you consume it:

(await uploadFile(formInstanceId, questionId, repeatId, filePath, isEquipment)).subscribe(result=> { /* ...Your code here... */ });

Async-await reference: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-1-7.html