1

I have the situation of a chain of of ES6 thenables/promises. The first promise in the chain is really an asynchronous method that determines whether a cache may be refreshed in the first place, and the subsequent methods in the chain do the actual refreshing.

The thing is that if the first method determines that I should not actually refresh the cache, I want to bomb out of the chain.... I don't need to do the rest.

The only way I have been able to get this to work is to store away the result of the testing method and the on each subsequent .then() in the chain, to test whether to actually do something or to return a simple Promise.resolve(null).

This seems like a bunch of extra silly code that shouldn't really need to be there.

My code below works.... error handling is correct.... but is there a better way to code this kind of pattern, where you only want to conditionally continue with a chain? A way that doesn't involve storing away the answer and then forcing a Promise.resolve() on every then()?

function asyncRefreshCache(wDb, forceRefresh) {
    var cachedDataVersions;
    var allowRefresh;
    return wDb.asyncCacheRefreshAllowed(forceRefresh) // Here I test whether I am allowed to really refresh the cache.
        .then(function (ar) {
            allowRefresh = ar;
            return allowRefresh 
                ? wDb.asyncGetCacheDataVersionsForRefresh() // Only do this if allowed above.
                : Promise.resolve(null); //Yuck.  Would love to just break out.  But how?
        })
        .then(function (dataVersions) {
            cachedDataVersions = dataVersions;
            return allowRefresh
                ? asyncServerFlexSearch({ dataVersions: dataVersions, includeInactiveFlag: true, onLoadFlag: true }) // Only do this if allowed above.
                : Promise.resolve(null); //Yuck.  Would love to just break out.  But how?
        })
        .then(function (serverResponse) {
            return allowRefresh
                ? wDb.asyncMergeCleanDataFromServerToCache(cachedDataVersions, serverResponse) // Only do this if allowed above.
                : Promise.resolve(null); //Yuck.  Would love to just break out.  But how?
        });
}

EDIT: This question was marked as a duplicate because of similar questions about Q Promises and JQuery Promises. And JQuery Promises aren't evern really promises. So my initial hope was that the spec and implementation for ES6 Promises would accomodate this seemingly important need and use case. It appears that this may not be the case. So the answers to those other questions may be the "correct" answer to this question, but they are not about ES6 Promises. So that seems different to me.

Stephan G
  • 3,289
  • 4
  • 30
  • 49
  • I don't think it does matter that the duplicate is not about ES6 promises, the pattern is exactly the same. – Bergi Jul 30 '16 at 07:57

1 Answers1

3

but is there a better way to code this kind of pattern, where you only want to conditionally continue with a chain?

You could throw an Error or use Promise.reject() from .then(), handle error and process error message or rejected promise reason at .catch()

guest271314
  • 1
  • 15
  • 104
  • 177
  • I appreciate the answer, and I see how it would work, but using exceptions (or rejections) to control expected program flow seems problematic. And not particularly readable either. It feels just as problematic as my solution. I wonder if the best solution is to just nest the promise. – Stephan G Jul 30 '16 at 07:08
  • Answer demonstrates only one possible approach. You could also check for `null` value at `.then()` and use existing pattern at Question. You do not need to use `Promise.resolve(null)` as `.then()` returns a new `Promise`; you could use ternary with `null` alone as value returned to chained `.then()`. Throwing error bypasses `.then(onFulfilled)` – guest271314 Jul 30 '16 at 07:16