redgeoff
redgeoff

Reputation: 3341

Combining promises and chaining

Is there a good design pattern for utilizing promises, while still supporting chaining? For example, let's say that we have something like:

function Foobar() {
  this.foo = function() {
    console.log('foo');
    return this;
  };

  this.bar = function () {
    console.log('bar');
    return this;
  };
}

var foobar = new Foobar();
foobar.foo().bar();

If instead we change the methods to use promises, e.g.

function Foobar() {
  this.foo = function() {
    var self = this;
    return new Promise(function (resolve, reject) {
      console.log('foo');
      resolve(self);
    });
  };
  ...
}

Is there a good way to do something like:

var foobar = new Foobar();
foobar.foo().bar().then(function () {
  // do something
});

Upvotes: 0

Views: 185

Answers (3)

thataustin
thataustin

Reputation: 2045

There is a handy .call method that allows you to call a method on the resolved value. I've found it pretty handy in a few cases: https://github.com/petkaantonov/bluebird/blob/master/API.md#callstring-propertyname--dynamic-arg---promise

Upvotes: 0

Bergi
Bergi

Reputation: 664336

If instead we change the methods to use promises, e.g.

this.foo = function() {
  var self = this;
  return new Promise(function (resolve, reject) {
    …
    resolve(self);
  });
};

I would recommend not to do that. This just begs for trouble. If your instance (or: its modification) is the result of your computation, then what is the state of your object (I assume you use OOP to encapsulate state) during that computation? What happened if this (or any other) method is called from a different process (thread) turn of the event loop? You'd have to go down the entire rabbit hole…

Try to use functional programming as far as you can.

Is there a good way to do something like:

new Foobar().foo().bar().then(function () {
  // do something
});

Yes, but you'd have to use .then after every invocation:

new Foobar().foo().then(function(foobar) {
  return foobar.bar();
}).then(function(barresult) {
  // do something
});

The Bluebird library (as do some others) even has a utility function for that .call(). So you'd do

new Foobar().foo().call("bar").then(function(barresult) {
  // do something
});

Upvotes: 4

homam
homam

Reputation: 1975

Just use then.

function Foobar() {
  this.foo = function() {
    var self = this;
    return new Promise(function (resolve, reject) {
      console.log('foo');
      resolve(self);
    });
  };
  this.bar = function() {
    var self = this;
    return new Promise(function (resolve, reject) {
      console.log('bar');
      resolve(self);
    });
  }
}

new Foobar().foo().then(function(foobar) { return foobar.bar(); });

Upvotes: 1

Related Questions