0

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?

4
  • 5
    Once your code became asynchronous - the rest would be asynchronous too, it's viral. Commented May 13, 2019 at 10:22
  • @zerkms - Very well put. But since the OP is returning an asynchronous kind of construct (and Observable), there's hope. :-) Commented May 13, 2019 at 10:31
  • @zerkms "It's viral"... lol. Commented May 13, 2019 at 10:35
  • @T.J.Crowder I reused it from the GPL, which is called a "viral license" en.wikipedia.org/wiki/Viral_license /cc briosheje Commented May 13, 2019 at 10:57

2 Answers 2

2

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.)

Sign up to request clarification or add additional context in comments.

Comments

1

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;
} 

2 Comments

This will return an Observable that emits an Observable when specialCase == true. The code should be return from(doSomethingAsync()).pipe(switchMap(val => observable));
Exactly, the consumer should not have to handle another Observable. @fridoo 's solution is what I wanted.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.