In such circumstances, the standard approach is to cache a lower-level promise.
Typically, you install a js plain object in some suitable external area as a promise cache and always look there first before calling your async process.
var promiseCache = {}; function foo() { if(!promiseCache.foo) { promiseCache.foo = doSomethingAsync(); } return promiseCache.foo; } function bar() { return foo().then(doSomethingElseAsync); }
Of course, there is nothing that would prevent you from caching a promise of a higher level, if necessary.
function bar() { if(!promiseCache.bar) { promiseCache.bar = foo().then(doSomethingElseAsync); } return promiseCache.bar; }
EDIT: forceRefresh function
You can force a function to update its cached promise by passing a (optional) parameter.
function foo(any, number, of, other, arguments, forceRefresh) { if(forceRefresh || !promiseCache.foo) { promiseCache.foo = doSomethingAsync(); } return promiseCache.foo; }
Making forceRefresh last argument, leaving it the same as passing false , and foo will use the promise with the cache, if available. Alternatively, go doSomethingAsync() true to ensure that doSomethingAsync() is called and the cached value is updated.
EDIT 2: setName () / getName ()
When using the forceRefresh mechanism in getName() :
setName(newName).then(getName.bind(null, true)); //set new name then read it back using forceRefresh.
Alternatively, omit the forceRefresh mechanism and, assuming the cache property is promiseCache.name :
setName(newName).then(function() { promiseCache.name = $.when(newName);
The first method is more elegant, the second is more effective.