Search code examples
javascriptpromiseqchaining

How to execute code at the very end of a promise chain in q


Let's say you have:

function setTimeoutPromise(ms) {
  var defer = Q.defer();
  setTimeout(defer.resolve, ms);
  return defer.promise;
}

and then you have something like:

function foo(ms) {
  return setTimeoutPromise(ms).then(function () {
    console.log('foo');
  });
}

function afterItAll() {
  console.log('after it all');
}

foo(100).then(function () {
  console.log('after foo');
}).then(afterItAll);

Is there a way to modify foo so that afterItAll is executed after the after foo block? e.g. something like:

function foo(ms) {
  return setTimeoutPromise(ms).then(function () {
    console.log('foo');
  }).SOMEPROMISECONSTRUCT(function () {
    console.log('after it all');
  });
}

foo(100).then(function () {
  console.log('after foo');
});

The reason I ask is that I am developing an API where the user will make several of these foo calls and it would greatly cut down on the user's code if the after foo code was automatically executed after these API calls. I know I can use a callback to accomplish this, but I'd really like to stick with just using promises.


Solution

  • No, there is no such promise construct. A promise does not - can not - know whether it is the end of a chain, or whether some other code will attach another link to it.

    There is however nothing wrong with combining promises and callback code:

    function foo(ms, within) {
      return setTimeoutPromise(ms).then(function () {
        console.log('foo');
      })
      .then(within)
      .then(function afterFooAll() { // possibly use `finally` here?
        console.log('cleanup');
      });
    }
    
    foo(100, function () {
      console.log('inside foo');
    }) // now returns a promise for cleanup been done
    

    I'm not sure what your actual use case is here, but you also might want to have a look at Bluebird's Promise.using resource management pattern.