Mohamed El Mahallawy
Mohamed El Mahallawy

Reputation: 13862

Angularjs dealing with promises and models

I am wondering what the best way to tackle down a has many relationship between models in angularjs and with promises. Allow me to show an example, I'd love your feedback on if there could be a better way to implement this.

A Surah has many Ayahs

My Surah model:

angular.module('qurancomApp')
  .service 'Surah', (Restangular, userOptions, Ayah) ->

    class Surah
      constructor: (obj) ->
        for key of obj
          @[key] = obj[key]

      getAyahs: (from, to) ->
        self = @
        @ayahs = Ayah.all
          surah_id: @id, from: from, to: to
        .then (ayahs) ->
          self.ayahs = ayahs

      @new: (id)->
        return Restangular.one('surahs', id).get().then (data)->
          return new Surah(data)

      @all: ->
        return Restangular.all("surahs").getList()

My Ayah model:

angular.module('qurancomApp')
  .service 'Ayah', (Restangular, userOptions) ->
    # AngularJS will instantiate a singleton by calling "new" on this function
    class Ayah
      constructor: (obj)->
        for key of obj
          @[key] = obj[key]

      @all: (hash) ->
        Restangular.one('surahs', hash.surah_id).getList 'ayat', 
          content: userOptions.content, quran: userOptions.quran, audio: userOptions.audio
        .then (data)->
          ayahs = data.map (ayah) ->
            # The ayah object is returned from Restangular and given all the properties that restangular gives it. For example, you can call
            # ayah.save() or ayah.remove() which will make API calls accordingly. This is power and will be perserved when creating the Ayah object
            return new Ayah(ayah)
          return ayahs

And the corresponding controller:

angular.module('qurancomApp')
  .controller 'AyahsCtrl', ($scope, $routeParams, Surah) ->
    rangeArray = $routeParams.range.split("-")

    Surah.new($routeParams.id).then (surah) ->
      $scope.currentSurah = surah
      console.log $scope.currentSurah.getAyahs(rangeArray[0], rangeArray[1])

Really, the question is: in the controller, I call function Surah.new() which then goes ahead and fetches that Surah from the backend, and then wants to create it's associated Ayahs, which I inject the Ayah model into the Surah model and have a promise on the Ayah model that is being digested in the Surah model, within the overall promise of Surah.new() function.

Is this a correct way to do this? Could there have been a better way?

Upvotes: 2

Views: 78

Answers (1)

Billy Moon
Billy Moon

Reputation: 58531

There could be an argument to make one API call, which returns everything you need, but there are compelling reasons the other way to. There is no general rule. More details about combining API requests here: https://softwareengineering.stackexchange.com/q/252362/20893

Assuming the API is as you have described, there could be advantages in responding to the first call to Surah before loading the Ayahs, but again, there are compelling reasons to do it the other way too.

If there is useful info in Surah that does not rely on Ayahs, you could render it, then each time an Ayah is loaded, also render that into the page (which takes more care to get right in interface, displaying loading spinners where appropriate, handling errors gracefully etc...).

If the info is only useful when loaded in it's entirety, then the way you have it now looks very reasonable to me.

Upvotes: 1

Related Questions