Problem 1: only one API request is allowed at a given time, so the real network requests are queued while there's one that has not been completed yet. An app can call the API level anytime and expecting a promise in return. When the API call is queued, the promise for the network request would be created at some point in the future - what to return to the app? That's how it can be solved with a deferred "proxy" promise:
var queue = [];
function callAPI (params) {
if (API_available) {
API_available = false;
return doRealNetRequest(params).then(function(data){
API_available = true;
continueRequests();
return data;
});
} else {
var deferred = Promise.defer();
function makeRequest() {
API_available = false;
doRealNetRequest(params).then(function(data) {
deferred.resolve(data);
API_available = true;
continueRequests();
}, deferred.reject);
}
queue.push(makeRequest);
return deferred.promise;
}
}
function continueRequests() {
if (queue.length) {
var makeRequest = queue.shift();
makeRequest();
}
}
Problem 2: some API calls are debounced so that the data to be sent is accumulated over time and then is sent in a batch when a timeout is reached. The app calling the API is expecting a promise in return.
var queue = null;
var timeout = 0;
function callAPI2(data) {
if (!queue) {
queue = {data: [], deferred: Promise.defer()};
}
queue.data.push(data);
clearTimeout(timeout);
timeout = setTimeout(processData, 10);
return queue.deferred.promise;
}
function processData() {
callAPI(queue.data).then(queue.deferred.resolve, queue.deferred.reject);
queue = null;
}
Since deferred is considered an anti-pattern, (see also When would someone need to create a deferred?), the question is - is it possible to achieve the same things without a deferred (or equivalent hacks like new Promise(function (resolve, reject) {outerVar = [resolve, reject]});
), using the standard Promise API?