简体   繁体   中英

Control when a `.then()` callback fires

I have a long chain of promises that wind through a module of my code. I don't know beforehand how many promises I'll wind through, nor do I have scope from any one promise to any other other promise (meaning I can't do a Promise.join() ).

My problem is that I have then() callbacks attached to multiple promises on this chain. How can I control which one is fired last?

UPDATE : Here's a simplified example:

var aFn = function () {
  return bFn().then(someFn);
};

var bFn = function () {
  return new Promise(function (resolve, reject) {
    if (a) return resolve();
    else return reject();
  });
};

aFn().then(anotherFn);

My problem is that the .then() in aFn().then(anotherFn) gets called before bFn().then(someFn) .

Here are a few code snippets that helps illustrate my issue:

strategy.js

execute: function (model, options) {
  options.url = this.policy.getUrl(model, this.method, options);
  options.collection = this.policy.getCollection(model, options);
  options.model = model;
  // This is a Promise that eventually calls get()
  return this.sync(model, options);
},

get: function (key, options) {
  var updateCollection = this._getUpdateCollection(options);
  var getFromCache = _.bind(this.store.get, this.store, key, options);
  if (updateCollection) {
    // updateCollection received a promise from store-helpers.js:proxyGetItem()
    return updateCollection().then(
      function (collection) {
        var modelResponse = collection.policy.findSameModel(collection.raw, options.model);
        return modelResponse ? modelResponse : getFromCache();
      },
      getFromCache
    );
  } else {
    return getFromCache();
  }
},

_getUpdateCollection: function (options) {
  var collection = options && options.collection;
  var collectionControl = collection && collection.sync && collection.sync.hoardControl;
  if (collection && collectionControl) {
  var collectionKey = collectionControl.policy.getKey(collection, options);
  return _.bind(function () {
    // store.get() passes the returned promise of store-helpers.js:proxyGetItem()
    return this.store.get(collectionKey, options).then(function (rawCollection) {
      return {
        control: collectionControl,
        policy: collectionControl.policy,
        key: collectionKey,
        raw: rawCollection
      };
    });
  }, this);
}

},

store.js

// Just a proxy function that wraps a synchronous get get: function (key, options) { return this.getItem.apply(this, arguments); },

getItem: StoreHelpers.proxyGetItem

store-helpers.js

proxyGetItem: function (key, options) {
  return Hoard.Promise.resolve()
    .then(_.bind(function () {
      return this.backend.getItem(key);
    }, this))
    .then(function (raw) {
      var storedValue = JSON.parse(raw);
      if (storedValue !== null) {
        return storedValue;
      } else {
        return Hoard.Promise.reject();
      }
   });
},

In a very different part of the app I also have:

var originalExecute = Hoard.Strategy.prototype.execute;
Hoard.Strategy.prototype.execute = function (model, options) {
    options.originalOptions = _.clone(options);
    if (options.saveToCacheFirst) 
        return originalExecute.call(this, model, options)
            .then(_.result(options.originalOptions, 'success'), _.result(options.originalOptions, 'error'));

    return originalExecute.call(this, model, options);
}

I would like for the .then() above to fire last, however when .resolve in store-helpers.js is fired, this last .then() callback is invoked.

My problem is that the .then() in aFn().then(anotherFn) gets called before bFn().then(someFn)

No it doesn't. As you've written the example, that expression is equivalent to

bFn().then(someFn).then(anotherFn)

- and while the .then() method does get called before someFn , the anotherFn callback does not.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM