fodma1
fodma1

Reputation: 3535

Javascript pattern for handling finished promise

I run into this every now and then:

return somethingThatReturnsAPromise()
  .then((response) => {
    soSomethingg(); // Eg; update the UI
    return response;
   });

Now I'm looking for something that is not expected to return anything and won't change the promise chain if I forget that:

return somethingThatReturnsAPromise()
  .whatImLookingFor((response) => {
    doSomething(); // Eg; update the UI
   })
   .then((response) => {
     // and this one should still be able to access response
   });

Maybe this goes against the idea of promises, but for me, it's a bit inconvenient since I can't pass arbitrary functions.

One idea is to compose a function:

const sideEffect = (callback) => {
  return (response) => {
    callback(response);
    return response;
  };
};

And I could use it as

return somethingThatReturnsAPromise()
  .then(sideEffect(doSomething));

But I'd prefer something instead of then is there something like that?

Note: I'm working with Angular 1.x so I need something like for that.

Upvotes: 2

Views: 63

Answers (3)

deceze
deceze

Reputation: 522250

I would assume that you're not really writing .then().then(), because you could collapse that into a single .then, but that your concern is really about returning the promise and having some external code add another then to the chain. In that case do this:

let p = somethingThatReturnsAPromise();
p.then(() => doSomething());
return p;

This allows the caller to attach additional thens to the original promise instead of chaining off of your .then, thereby receiving the original promise's value. This is called branching the promise chain.

Upvotes: 2

T.J. Crowder
T.J. Crowder

Reputation: 1074676

Maybe this goes against the idea of promises

Slightly, promise chains are pipelines where then handlers transform things at each stage. But it's perfectly valid to want to pass through the value unchanged.

One idea is to compose a function:

Indeed the first thing that came to mind, and how I'd do it.

But I'd prefer something instead of then is there something like that?

There isn't. You could add it for your own projects (I wouldn't in a library) by adding it to Promise.prototype. Or you could give yourselve a Promise subclass and add it there.

With a Promise sublass you'd do something like:

return MyPromise.resolve(somethingThatReturnsAPromise())
  .thenSide(soSomethingg); // Eg; update the UI

...where thenSide is your method that's then but passing the original value back unchanged, e.g.:

class MyPromise extends Promise {
    thenSide(callback) {
        this.then(callback);
        return this;
    }
}

or

class MyPromise extends Promise {
    thenSide(callback) {
        this.then(callback);
        return MyPromise.resolve(this);
    }
}

...depending on whether you're bothered about thenSide returning the same promise (since then always returns a new one).

Upvotes: 2

jlaitio
jlaitio

Reputation: 1948

As far as I know (I could well be wrong) the wrapper method for "pass-through" side-effects is an idiomatic way to do what you want.

Alternatively (if you need the same response in multiple places) you can break up the promise chain when you encounter a situation like this.

Upvotes: 0

Related Questions