0

In this scenario the requirement is to get the data with an Http request if the data is not in a buffer. If it's in the buffer, use it from there without the Http request.

I tried the code below but it doesn't make much sense; if the data is in the buffer I don't know if I should return from the function doing nothing or return the deferred promise. Any thoughts?

  var dataBuffer = null;

  var getData = function() {

     var deferred = $q.defer();

     if (dataBuffer != null) {  // this is the part I'm not convinced
         deferred.resolve();
         return;
     }  


     $http.get('/some/url/')
       .success(function(data) { 
               dataBuffer = data;
               deferred.resolve();
       })
       .error(function(data) {
               deferred.reject();
       });

     return deferred.promise;
  };

Invoked in the following way:

     var promise = getData();
     promise.then (
           function(response) { 
              dataBuffer = .... // dataBuffer contains data
              }
           );
ps0604
  • 1,227
  • 23
  • 133
  • 330

3 Answers3

3

There is a clean simple way to use promises when you're not sure which is the code you're executing is asynchronous or not and it's using $q.when So the code can be:

var getData = function() {
    return $q.when(dataBuffer ? dataBuffer: $http.get('/some/url')) 
};

Then when calling getData you can use the same code you posted or just simply:

getData()
       .then(function(response){//... 
       })
       .catch(function(err){//..
       });
teleaziz
  • 2,220
  • 1
  • 19
  • 25
1

Beware of the deferred antipattern. You can accomplish what you are trying to do very cleanly, like this:

var dataBuffer;
var getData = function() {
    if (dataBuffer) {
        // return a resolved promise for  dataBuffer  if it is already populated
        return $q.when(dataBuffer);
    }  

    $http.get('/some/url/')
    .then(function (data) { 
        dataBuffer = data.data;
        return dataBuffer;
    });
};

getData().then(function (data) { 
    // data contains the data you want
})
.catch(function (error) {
    // error occurred.
});


dataBuffer should not be accessed outside of your getData function. To make this perfectly clear, you can wrap them together in an IIFE, although this is optional:
var getData = (function () {
    var dataBuffer;
    return function() {
        if (dataBuffer) {
            // return a resolved promise for  dataBuffer  if it is already populated
            return $q.when(dataBuffer);
        }  

        $http.get('/some/url/')
        .then(function (data) { 
            dataBuffer = data.data;
            return dataBuffer;
        });
    };
})();

getData().then(..etc etc etc...);


As a final note, remember that you can use $http's built-in caching features, and not have to reinvent the wheel with your own buffers:
// much simpler, isn't it?
var getData = function() {
    $http.get('/some/url/', { cache: true })  // enable caching
    .then(function (data) { return data.data });
};

getData().then(...etc etc etc...);
Community
  • 1
  • 1
JLRishe
  • 99,490
  • 19
  • 131
  • 169
0

Why dont you enable cache instead of handling the buffer manually.

   $http.get('/some/url/',{ cache: true})
   .success(function(data) { 
           deferred.resolve(data);
   })
   .error(function(data) {
           deferred.reject();
   });
Karthik
  • 1,377
  • 6
  • 8
  • `deferred.resolve(data)` you may want to access data in the success callback – topheman Jan 02 '15 at 22:56
  • I can't; I simplified the example but the scenario involves an array of data where each entry in the array is populated from the responses. Also, I would need to have control on when to clear the $http cache. – ps0604 Jan 02 '15 at 22:58
  • Can you provide more detail in your question then? I suspect that there is a better way to do what you are trying to do. – AJ Richardson Jan 03 '15 at 06:20