2

I find myself running into a few circular dependency issues among my services, which probably means they're just built incorrectly.

Full Plunk

The basics - this works fine:

.factory('bookCollection', function($http, urls, user) {
      var books = [];

      return {
          data: books,
          getBooks: getBooks,
          reset: resetCollection,
          addBook: addToCollection
      };

      ///////////////////////////////////

      function getBooks() {
          var params = { 
            user: user.current
          };

          return $http.get(urls.getBooks, { params: params })
              .then(function(res) {
                  books = res.data;
                  return books;
              });
      }

      function resetCollection() {
          books = [];
      }

      function addToCollection(book) {
          books.push(book);
          persistCollection(books);
      }

      function persistCollection(books) {
          return $http.post(urls.postBooks, books)
              .then(function(res) {
                  return res.status;
              });
      }
})

.factory('user', function($http, urls) {
      var currentUser = {};

      return {
          current: currentUser,
          getUser: fetchCurrentUser
      };

      ///////////////////////////////////

      function fetchCurrentUser(userId) {
          return $http.get(urls.getUser, { params: { id: userId }})
              .then(function(res) {
                    angular.copy(res.data, currentUser);
              });
      }
});

Now I want to introduce the ability to reset the current bookCollection when I fetch a new user. But if I add bookCollection as a dependency to user then I will have created a circular dependency.

How else can I make this bookCollection.reset process automatic so that every time I fetch a new user I wipe the collection?

Also, as a side note, I'm wondering if my bookCollection.data should be its own service separate from the methods that interact with the server, since one is just a "store" for the data and the other is a communication layer.

diplosaurus
  • 2,538
  • 5
  • 25
  • 53
  • This should probably be handled in a controller. The services should only know about fetching data. – Paul Nispel Jul 01 '15 at 04:11
  • @PaulNispel You may be right, but this seems counter to what's advertised. First off if I have many places around the app where this user is reset then I'm repeating code. Secondly this action is never affecting the scope of a view, so I feel like a controller isn't the correct choice. – diplosaurus Jul 01 '15 at 04:36
  • 1
    communication between angular modules is a not well solved problem. There are three solutions: 1) pass in a third factory that simply stores the state of the current user, listen to this state and on change update the book store 2) use $rootScope broadcast/emit 3) handle it in your controller – Paul Nispel Jul 01 '15 at 04:39
  • 1
    Paul is right. That looks like part of viewmodel/controller. Also you can pass user directly to getBooks, which removed modules dependency at all. – mikalai Jul 01 '15 at 14:28
  • @mikalai While it doesn't seem like a big deal to have it in the controller for this simple example, what happens if there are 9 places throughout the app where `fetchCurrentUser` is called, in each of those places the controller needs to manually call `resetCollection`? What if a new developer starts on the project, they are going to need to know that every time you call `fetchCurrentUser` you must also call `resetCollection`? This seems doubtful to me. – diplosaurus Jul 01 '15 at 17:01

1 Answers1

0

Ended up using the top solution from this post:

angular JS - communicate between non-dependend services

Essentially created a third service to use as an "event bus" and foster communication between services without repeating method calls in controllers or overusing $rootScope.

Community
  • 1
  • 1
diplosaurus
  • 2,538
  • 5
  • 25
  • 53