joshhunt
joshhunt

Reputation: 5335

RxJS: Conditional map or mergeMap

If I have a method that sometimes returns a string and sometimes returns a promise that results in a string how can I chain that in my observable?

Example

function doSomething() {
    if (Math.random() < 0.5) {
        return 'test';
    }

    return new Promise(resolve => resolve('test'));
}

const example = of(undefined).pipe(
    mergeMap(() => doSomething())
);

const subscribe = example.subscribe(val => console.log(val));

I would like to always log "test".

Upvotes: 7

Views: 9104

Answers (2)

cartant
cartant

Reputation: 58400

One way of solving the problem would be to make the function passed to mergeMap an async function and to await the return value of doSomething, like this:

const example = of(undefined).pipe(
  mergeMap(async () => await doSomething())
);

You can do this because mergeMap expects the function to return an ObservableInput and a promise is a valid ObservableInput.

Doing so takes advantage of that fact await will accept either a promise or an ordinary value - to which the promise returned by the async function will resolve.

Upvotes: 3

alexc
alexc

Reputation: 208

function doSomething() {
    if (Math.random() < 0.5) {
        return 'test';
    }

    return new Promise(resolve => resolve('test'));
}

const example = of(undefined)
  .pipe(
    map(() => doSomething()),
    mergeMap(value => value instanceof Promise ? from(value) : from([value]))
  );

const subscribe = example.subscribe(val => console.log(val));

Not that you asked, but your code is an anti-pattern. Your doSomething method should always return the same value type, in your case, either a string or a promise.

Upvotes: 1

Related Questions