2013-01-08 10 views
6

Oczywiście brakuje mi pojęcia/zrozumienia i zdecydowanie javascript OO!Czy mogę mieć wiele instancji modułu RequireJS?

Uwielbiam używać RequireJS, a moja aplikacja internetowa wygląda teraz bardziej jak aplikacja strukturalna, a nie cała kupa zwariowanego kodu.

Po prostu staram się zrozumieć, w jaki sposób/jeśli jest to możliwe.

Mam moduł, który działa jako moduł bazowy dataservice zwanego dataservice_base następująco:

define(['dataservices/dataservice'], function (dataservice) { 

    // Private:  Route URL 
    this.route = '/api/route-not-set/'; 
    var setRoute = function (setRoute) { 
     this.route = setRoute; 
     return; 
    } 

    // Private: Return route with/without id 
    var routeUrl = function (route, id) { 
     console.log('** Setting route to: ' + route); 
     return route + (id || "") 
    } 

    // Private: Returns all entities for given route 
    getAllEntities = function (callbacks) { 
     return dataservice.ajaxRequest('get', routeUrl()) 
     .done(callbacks.success) 
     .fail(callbacks.error) 
    }; 

    getEntitiesById = function (id, callbacks) { 
     return dataservice.ajaxRequest('get', routeUrl(this.route, id)) 
     .done(callbacks.success) 
     .fail(callbacks.error) 
    }; 

    putEntity = function (id, data, callbacks) { 
     return dataservice.ajaxRequest('put', routeUrl(this.route, id), data) 
     .done(callbacks.success) 
     .fail(callbacks.error) 
    }; 

    postEntity = function (data, callbacks) { 
     return dataservice.ajaxRequest('post', routeUrl(this.route), data) 
     .done(callbacks.success) 
     .fail(callbacks.error) 
    }; 

    deleteEntity = function (id, data, callbacks) { 
     return dataservice.ajaxRequest('delete', routeUrl(this.route, id), data) 
     .done(callbacks.success) 
     .fail(callbacks.error) 
    }; 

    // Public:  Return public interface 
    return { 
     setRoute: setRoute, 
     getAllEntities: getAllEntities, 
     getEntitiesById: getEntitiesById, 
     putEntity: putEntity, 
     postEntity: postEntity, 
     deleteEntity: deleteEntity 
    }; 

}); 

Jak widać, jestem przedstawieniu dataservices/dataservice, która jest faktycznie mechanizm rdzeń wywołanie AJAX (nie pokazano, ale tak naprawdę tylko podstawowe wywołanie ajax jQuery w opakowaniu).

Co staram się zrobić, to pozwolić to moduł podstawowy dataservice być „instancja” w następujący sposób (w innym module - tylko fragment kodu):

define(['dataservices/dataservice_base', 'dataservices/dataservice_base', 'dataservices/dataservice_base'], function (dataservice_profile, dataservice_qualifications, dataservice_subjects) { 

    // Set the service route(s) 
    dataservice_profile.setRoute('/api/profile/'); 
    dataservice_qualifications.setRoute('/api/qualification/'); 
    dataservice_subjects.setRoute('/api/subject/'); 

Jak widać, staram się to samo dataservice_base (zdefiniowany powyżej) 3 razy, ale w odnośnikach funkcyjnych, staram się odnieść do każdej instancji o nazwie Vars tj:

dataservice_profile, dataservice_qualifications, dataservice_subjects

.. i oczywiście próbuję ustawić unikalną wartość setRoute dla każdej z tych instancji, która będzie dalej używana w module .. przy jednoczesnym wykorzystaniu wspólnych wywołań (get, puts, posts itp.).

Oczywiście brakuje mi tu kilku rzeczy .. ale jakakolwiek pomoc, która wskazywałaby mnie na drodze, byłaby bardzo wdzięcznie przyjęta !!

Pozdrawiamy, David.

Odpowiedz

6

Myślę, że musisz uwzględnić swoją zależność tylko raz i użyć słowa kluczowego new. Być może trzeba będzie byłaby więc, że wspólne funkcje są w module zależności:

define(['dataservices/dataservice'], function (dataservice) { 
    var dataservice_profile = new dataservice(); 
    var dataservice_qualifications = new dataservice(); 
    var dataservice_subjects = new dataservice(); 

    // Set the service route(s) 
    dataservice_profile.setRoute('/api/profile/'); 
    dataservice_qualifications.setRoute('/api/qualification/'); 
    dataservice_subjects.setRoute('/api/subject/'); 

    // define needs to return something 
    return { 
     profile: dataservice_profile, 
     qualifications: dataservice_qualifications, 
     subjects: dataservice_subjects 
    }; 
}); 
3

Tak, mózg zamarzaniu lub cokolwiek .. problemy pracuje sam czasem!

Więc, jak wspomniał @gothoth, całkiem słusznie musiałem oczyścić umysł i trochę przemyśleć!

skończyło się z ponownego uwzględnione modułu dataservice_base następująco:

define(['dataservices/dataservice'], function (dataservice) { 

    // Set any class/static vars 

    // Set the instance function 
    function dataservice_base(setRoute) { 

     var self = this; 

     self.route = setRoute; 
     console.log('setting route: ' + self.route); 

     function routeUrl(route, id) { 
      console.log('** Setting route to: ' + route); 
      return route + (id || "") 
     } 

     self.getAllEntities = function (callbacks) { 
      return dataservice.ajaxRequest('get', routeUrl()) 
      .done(callbacks.success) 
      .fail(callbacks.error) 
     } 

     self.getEntitiesById = function (id, callbacks) { 
      return dataservice.ajaxRequest('get', routeUrl(self.route, id)) 
      .done(callbacks.success) 
      .fail(callbacks.error) 
     } 

     self.putEntity = function (id, data, callbacks) { 
      return dataservice.ajaxRequest('put', routeUrl(self.route, id), data) 
      .done(callbacks.success) 
      .fail(callbacks.error) 
     } 

     self.postEntity = function (data, callbacks) { 
      return dataservice.ajaxRequest('post', routeUrl(self.route), data) 
      .done(callbacks.success) 
      .fail(callbacks.error) 
     } 

     self.deleteEntity = function (id, data, callbacks) { 
      return dataservice.ajaxRequest('delete', routeUrl(self.route, id), data) 
      .done(callbacks.success) 
      .fail(callbacks.error) 
     } 

    } // eof instance 

    return dataservice_base; 
} 

i oczywiście ponownie @asgoth wspomniano, że wystarczy oczywiście zawierać jedno odniesienie do modułu dataservice_base i rzędzie dla moich potrzeb w następujący sposób:

define(['dataservices/dataservice_base','viewmodels/viewmodel_profile', 'viewmodels/viewmodel_qualifications', 'viewmodels/viewmodel_subjects', 'app/common'], function (dataservice_base, viewmodel_profile, viewmodel_qualifications, viewmodel_subjects, common) { 

    var dataservice_profile = new dataservice_base('/api/profile/'); 
    var dataservice_qualifications = new dataservice_base('/api/qualification/'); 
    var dataservice_subjects = new dataservice_base('/api/subject/'); 

    // do whatever now with those instance objects... 
} 

SO .. teraz działa!

Sądzę, że jedyną rzeczą, którą muszę zrobić, jest sprawdzenie procesu czyszczenia, aby upewnić się, że te obiekty zostaną wypuszczone .. jednak będzie ich tylko kilka ... ale wciąż ..

dzięki jeszcze raz @asgoth

+2

Walczyłem z tą koncepcją. Ta odpowiedź czyni ją bardzo jasną! ... Przypuszczam, że kluczem tutaj jest zrozumienie, że RequireJS zawsze zwraca to samo wystąpienie modułu, bez względu na to, ile razy "wymagacie" tego. Jeśli moduł zwraca funkcję konstruktora zamiast statycznego obiektu, można utworzyć wystąpienia z funkcji konstruktora, używając nowego słowa kluczowego w module klienta. Ta sama funkcja konstruktora jest zwracana przez RequireJS za każdym razem, ale tego właśnie chcemy, ponieważ jest to szablon, klasa. Zadaniem modułu klienta jest tworzenie instancji z tej klasy. –

+0

"" "Przypuszczam, że kluczem tutaj jest zrozumienie, że RequireJS zawsze zwraca to samo wystąpienie modułu, bez względu na to, ile razy" wymaga "tego modułu." "" Prawie. Wykonuje buforowanie pierwszej wymaganej instancji, ale TYLKO jeśli jest to ten sam dokładny moduł na tej samej dokładnej ścieżce. Oznacza to, że jeśli masz tę samą bibliotekę "xxx" w 2 różnych ścieżkach (dla różnych części swojej aplikacji), takich jak: app/modules/foo/xxx i app/modules/bar/xxx, a następnie wymagając każdej z nich przynieść inna instancja. Może się to stać np. jeśli masz inny pakiet package.json dla każdego modułu i pytają o tę samą bibliotekę. – Hejazzman

1

Wystarczy powrócić do funkcji zamiast obiektu jak to

return function(){ 
    return { 
     // your public interface goes here 
    }; 
} 

Teraz można tworzyć nowe instancje swojej wtyczki z new componentName().