javascript - Promises for promises that are yet to be created without using the deferred [anti]pattern -


problem 1: 1 api request allowed @ given time, real network requests queued while there's 1 has not been completed yet. app can call api level anytime , expecting promise in return. when api call queued, promise network request created @ point in future - return app? that's how can solved 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: api calls debounced data sent accumulated on time , sent in batch when timeout reached. app calling api expecting 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 considered anti-pattern, (see when need create deferred?), question - possible achieve same things without deferred (or equivalent hacks new promise(function (resolve, reject) {outervar = [resolve, reject]});), using standard promise api?

promises promises yet created

…are easy build chaining then invocation callback creates promise promise represents availability create in future.

if making promise promise, should never use deferred pattern. should use deferreds or promise constructor if , if there asynchronous want wait for, , it not involve promises. in other cases, should compose multiple promises.

when say

when api call queued, promise network request created @ point in future

then should not create deferred can later resolve promise once created (or worse, resolve promises results once promise settles), rather should promise point in future @ network reqest made. you're going write

return waitforendofqueue().then(makenetworkrequest); 

and of course we're going need mutate queue respectively.

var queue_ready = promise.resolve(true); function callapi(params) {   var result = queue_ready.then(function(api_available) {     return dorealnetrequest(params);   });   queue_ready = result.then(function() {     return true;   });   return result; } 

this has additional benefit need explicitly deal errors in queue. here, every call returns rejected promise once 1 request failed (you'll want change that) - in original code, queue got stuck (and didn't notice).

the second case bit more complicated, involve settimeout call. asynchronous primitive need manually build promise - timeout, , nothing else. again, we're going promise timeout, , chain our api call promise want return.

function timeoutqueue(timeout) {   var data = [], timer = 0;   this.promise = new promise(resolve => {     this.renew = () => {       cleartimeout(timer);       timer = settimeout(resolve, timeout);     };   }).then(() => {     this.constructor(timeout); // re-initialise     return data;   });   this.add = (datum) => {     data.push(datum);     this.renew();     return this.promise;   }; }  var queue = new timeoutqueue(10); function callapi2(data) {   return queue.add(data).then(callapi); } 

you can see here a) how debouncing logic factored out of callapi2 (which might not have been necessary makes nice point) , b) how promise constructor concerns timeout , nothing else. doesn't need "leak" resolve function deferred would, thing makes available outside renew function allows extending timer.


Comments

Popular posts from this blog

PySide and Qt Properties: Connecting signals from Python to QML -

c# - DevExpress.Wpf.Grid.InfiniteGridSizeException was unhandled -

scala - 'wrong top statement declaration' when using slick in IntelliJ -