title: Angular Service asynchronous singleton for UI-Router
body: <p>I am using <a href="https://github.com/angular-ui/ui-router" rel="nofollow noreferrer">UI-Router</a> for an Angular app.  I have data which I am pulling through an <code>$http</code> asynchronous call that is used to create a connection object of sorts.  My goal is to have some way of creating this object and making it available as a singleton.  Although the chances of it happening are rare, I am looking to avoid timing issues where the <code>socket</code> property in the Service is assigned asynchronously.  When a different state in the router wants to get or create another connection object, it will do so through the singleton so that the same connection can be used instead of creating another connection.</p>
  
  <p>Below is a skeleton of some code that I am attempting to get to work.  I'm not sure if something can be done with the <code>resolve</code> of the state.</p>
  
  <p>Any thoughts or suggestions on how this can be done?</p>
  
  <pre><code>var myapp = angular.module('me', ['ui.router'])
  .service('connectionService', ['$http', function($http) {
      var socket;
  
      // Somehow call and store result of $http in a singleton
      // Would the $http.get get put in some kind of function? If so, how should it get called 
      // and returned so that a user of the service can get the 'socket' object synchronously?
          $http.get("something/that/returns/data")
              .success(function (result) {
                  this.socket= createConnection(result.data);
              })
              .error(function (err) {
                  //handle error
              })
  
      var getSocket= function() {
          if (!this.socket) {
              return createNewSocket();
          } else {
              return this.socket;
          }
      }
  }])
  
  myapp.config(function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise("home");
  
      $stateProvider
          .state('home', {
              url: "/home",
              templateUrl: "home.html",
              resolve: {
                  socket: // ??? Can something be done here ???
              },
              controller: function(socket) {
                  // I can haz socket?
              }
          })
          .state('nextState', {
              url: "/next",
              templateUrl: "next.html",
              resolve: {
                  socket: // Should be the same socket object as from the home state
              },
              controller: function(socket) {
                  // I can haz same socket?
              }
          })
  })
  </code></pre>
  
  <hr>
  
  <p><strong>Update</strong></p>
  
  <p>In the process of trying to explain the issue better, I have changed the original code a couple of times.  The comments people have left corrected definite errors I was having.  I have reverted the above code to the way it originally was, and have added new code below.  The issue that I am still having is that the <code>resolve</code> on the ui-router state isn't resolving before entering the controller.  So, when calling an <code>emit()</code> on the <code>socket</code> object that is supposed to be resolved, I an error of "Cannot read property 'emit' of undefined".  I also still want the <code>socket</code> objects to be the same object between the states.  I would appreciate any other suggestions or comments to steer me in the right direction.</p>
  
  <pre><code>var myapp = angular.module('me', ['ui.router'])
  .service('connectionService', ['$http', function($http) {
      var socket;
  
      // Somehow call and store result of $http in a singleton
      // Would the $http.get get put in some kind of function? If so, how should it get called 
      // and returned so that a user of the service can get the 'socket' object synchronously?
      $http.get("something/that/returns/data")
          .then(function (result) {
              socket = createConnection(result.data);
          }, function (err) {
              // handle error
          });
  
      var getSocket = function() {
          if (!socket) {
              // handle error
          } else {
              return socket;
          }
      }
  }])
  
  myapp.config(function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise("home");
  
      $stateProvider
          .state('home', {
              url: "/home",
              templateUrl: "home.html",
              resolve: {
                  socket: function(connectionService) {
                      return connectionService.getSocket();
                  }
              },
              controller: function(socket) {
                  socket.emit("some msg");
              }
          })
          .state('nextState', {
              url: "/next",
              templateUrl: "next.html",
              resolve: {
                  socket: function(connectionService) {
                      return connectionService.getSocket();
                  }
              },
              controller: function(socket) {
                  socket.emit("some other msg");
              }
          })
  })
  </code></pre>
  
  <hr>
  
  <p><strong>Update 2</strong></p>
  
  <p>Working solution, but this is not as elegant as <a href="https://stackoverflow.com/users/2652883/muli-yulzary">Muli Yulzari</a>'s answer that has been accepted as the correct answer.</p>
  
  <p>I looked into creating my own promise and returning that as something for ui-router to resolve.  Based on all of my debugging and stack traces, there is only one connection created among the states and the entering into the controller is deferred until the connection is resolved.  So, I believe this is a working solution.  I also have a version of the code that handles an <code>onConnect</code> event on the connection before resolving the promise, but I have left it out for the sake of brevity.</p>
  
  <pre><code>var myapp = angular.module('me', ['ui.router'])
  .service('connectionService', ['$http', '$q', function($http, $q) {
      var socket;
  
      this.getSocket = function() {
          if (!socket) {
              var deferred = $q.defer();
  
              $http.get("something/that/returns/data")
                  .then(function (result) {
                      socket = createConnection(result.data);
                      deferred.resolve(socket);
                  }, function (err) {
                      // handle error
                      deferred.reject(socket);
                  });
  
              return deferred.promise;
          } else {
              return socket;
          }
      }
  }])
  
  myapp.config(function($stateProvider, $urlRouterProvider) {
      $urlRouterProvider.otherwise("home");
  
      $stateProvider
          .state('home', {
              url: "/home",
              templateUrl: "home.html",
              resolve: {
                  socket: function(connectionService) {
                      return connectionService.getSocket();
                  }
              },
              controller: function(socket) {
                  socket.emit("some msg");
              }
          })
          .state('nextState', {
              url: "/next",
              templateUrl: "next.html",
              resolve: {
                  socket: function(connectionService) {
                      return connectionService.getSocket();
                  }
              },
              controller: function(socket) {
                  socket.emit("some other msg");
              }
          })
  })
  </code></pre>