I want to construct a function that creates and returns an Observable. Depending on the parameters this function receives it should either create the Observable and return it directly or (in a special case) call another asynchronous function before returning the Observable.

Abstract example:

async function doSomethingAsync(){
    return 'success';
}

function returnObservable(specialCase: boolean): Observable<any>
    const observable = new Observable(
        observer =>
            observer.next(1)
        }
    );

    if(specialCase) {
        doSomethingAsync().then(
            then => {
                // this does not work, of course, but that's what I would like to be able to do
                return observable;
            }
        )       
    } else {
        return observable;
    }
} 

Now my problem is that appearently I cannot call an asynchronous function and then return the Observable. I could make this whole returnObservable function asynchronous and just await the doSomethingAsync but then the returnObservable function would return a Promise returning an Observable - and that's not what I want. The consumer of this function should receive the Observable directly.

I hope I could make my problem clear. Is there any way to solve this problem?

2 Answers

2
T.J. Crowder On

Is there any way to solve this problem?

Because you're returning an Observable, there may be.

It's impossible to have returnObservable block synchronously until an async function returns. But, you can have it return an Observable that (optionally) won't emit any events until the async function completes. You could even have it not even call the async function until/unless something subscribes to it.

Something vaguely like:

function returnObservable(specialCase: boolean): Observable<any>
    const promise = specialCase ? doSomethingAsync() : Promise.resolve();
    const observable = new Observable(
        observer => {
            promise
            .then(() => {
                observer.next(1);
            })
            .catch(error => {
                // deal with the error
            });
        }
    );

    return observable;
} 

(You might even be able to use fromPromise. I'm not strong enough on Rx.js to be sure.)

1
Alfredo NoctiS Salzillo On

Transform the promise into an observable:

async function doSomethingAsync(){
    return 'success';
}

function returnObservable(specialCase: boolean): Observable<any>
    const observable = new Observable(
        observer =>
            observer.next(1)
        }
    );

    if(specialCase) {
        return Observable.from(doSomethingAsync().then(
            then => {
                // this does not work, of course, but that's what I would like to be able to do
                return observable;
            }
        ));
    }
    return observable;
}