1

Here is my situation. For simplicity, let's assume I have a system called a BookListManager that manages lists of library books.

app.service('BookListManager', function(){
    var BookListManager = {
        activeBookList:null,
        addNewBookList:function(){
            //create new BookList()
            //set new BookList to activeBookList;
        }
    }
}

I then have a factory that creates a BookList object.

app.factory('BookList', function(){
    var BookList = function(params){
         //RESTful request via resource to fetch booklist data.
         //Assign booklist data to this object.
         //Create Book object for each book in this book list.
    }
    return BookList;
});

And now I have a Book object that belongs within each book list.

 app.factory('Book', function(){
     var Book = function(){
        //RESTful resource call for book data.
        //Assign book data to Book object.
     }

     return Book;
 });

How can I create a promise chain to wait until after both the BookList and Books have finished collecting their data from the AJAX requests before assigning it as the activeBookList inside my BookListManager service?

I am using the latest version of Angular. Thanks.

Zerocaliber
  • 67
  • 1
  • 4
  • I argue against the ActiveRecord pattern and in favor of using a repository - A book should not be in charge of this. – Benjamin Gruenbaum Sep 15 '14 at 18:19
  • possible duplicate of [Is it bad practice to have a constructor function return a Promise?](http://stackoverflow.com/q/24398699/1048572)? – Bergi Sep 16 '14 at 13:36

1 Answers1

0

Well, in my opinion constructors should not perform any I/O since I think that should be simple. However, given your different coding style, using your current pattern we'd have no choice but to make Book and BookList a promise:

 app.factory('Book', function(){
     var Book = function(){
         var data = $http.get(...); // or ngResource call
         data.then(function(resp){
            // populate book fields, for example
            this.author = resp.data.author;
         }.bind(this))
         this.then = data.then; // make the book a thenable
     };

     return Book;
 });

This would let you write code like:

var b = new Book();
b.then(function(){
   // I know the book is loaded here
})

Similarly, you can do this for the BookList:

app.factory('BookList', function(){
    var BookList = function(params){
         var p = $http.get(...); // fetch book list data, could be ngResource too
         var p2 = p.then(function(list){
             this.listName = list.data.name;
             var booksP = $q.all(list.data.books.map(function(bookId){
                 return new Book(bookId); // fetch param
             });
             return booksP; // return promise over books loading 
         }.bind(this))
         this.then = p2.then; // make this a promise that resolves on load
    };
    return BookList;
});

Which would let you do:

var bl = new BookList(...);
bl.then(function(){
    // all data in the book list loaded
})
Benjamin Gruenbaum
  • 270,886
  • 87
  • 504
  • 504
  • Thanks. And yeah, I was hoping to avoid doing this. Instead I opted to make the factory handle fetching of the data and return a promise that eventually returns an instance of the object I was trying to create. That being said, I appreciate your effort in answering the question using my original methods. – Zerocaliber Sep 18 '14 at 16:31