Siddharth
Siddharth

Reputation: 545

Calling $http only once in a controller

I have a controller for the landing page. My problem is that $http gets called again whenever I view the page since the controllers for that view gets executed resulting in $http executing all the time.

app.controller('landingCtrl', function($scope, $splash, $http, sentiment) {

    //get JSON DATA FROM SERVER 
    var restURL = {};
    restURL.getSentiments = "http://localhost:3000/getSent";

    //get JSON DATA FROM SERVER  
    $http.get(restURL.getSentiments).then(function(res) {
        log(res);
        return res;
    }); /*AJAX ENDS*/

});

Is there any way where I call my $http only once or have some freedom of control as when I want to call? As of now the $http is always getting executed.

Upvotes: 1

Views: 1162

Answers (2)

Krzysztof Safjanowski
Krzysztof Safjanowski

Reputation: 7438

Lets indrocude once from function programming. The wrapped function is fired only once because a fn variable is used to ensure the function is only executed once.

angular.module('app', [])
  .controller('onceCtrl', function($scope, messages) {

    $scope.messages = messages.get()

  }).factory('messages', function($timeout, once) {

    var messages = []

    return {
      get: once(function() {
        $timeout(function() { // some delay to simulate $http request
          messages.push({
            date: Date.now()
          })
        }, 1000)
        return messages
      })
    }


  }).factory('once', function() {
    return function once(fn, context) {
      var result;

      return function() {
        if (fn) {
          result = fn.apply(context || this, arguments);
          fn = null;
        }

        return result;
      };
    }
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app">
  <div ng-controller="onceCtrl">
    First exection {{ messages }}
  </div>
  <div ng-controller="onceCtrl">
    Second execution {{ messages }}
  </div>
  <div ng-controller="onceCtrl">
    Third execution {{ messages }}
  </div>
</div>

Upvotes: 0

BastianW
BastianW

Reputation: 270

To keep my code clean and structured, I wrap those $http calls in services. Also when you have different REST calls, you have less code to change, when you have to edit your api path.

Here is an example:

'use strict';

angular.module('YourApp')
  .service('Sentiments', function ($http) {
    var sentiments = [];
    var api = 'http://localhost:3000/getSent';

    return {
        all: function(callback) {
            var cb = callback || angular.noop;
            if(sentiments.length !== 0) {
                cb(sentiments);
            }else{
                $http.get(api)
                    .success(function(result) {
                        sentiments = result;
                        cb(result);
                    })
                    .error(function() {
                        cb();
                    })
            }
        }
    }
  })

  .controller('landingCtrl', function ($scope, Sentiments) {        
    Sentiments.all(function(sentiments) {
      $scope.sentiments = sentiments;
    });
  });

Upvotes: 0

Related Questions