-
Notifications
You must be signed in to change notification settings - Fork 1
JS Data : gestion des objets
#Pourquoi JS-Data ?
JS-Data permet de transformer le frontend en une véritable application autonome avec ses données et pas seulement une couche qui "affiche" le backend. JS-Data est ainsi le "backend du frontend", il communique avec le backend de manière à minimiser les requêtes HTTP. Par exemple, quand un User
est chargé dans JS-Data, il ne sera pas redemandé au backend. Ainsi quand on navigue sur le site, la première fois les informations des pages mettent longtemps à se charger à cause du delai de la requête au backend, puis les fois suivantes le chargement est instantané car les données se trouvent dans le cache de JS-Data.
#Concepts de JSData
L'information est organisée autour de trois objets : Resource
, Record
et Mapper
.
Une Resource
est une abstraction de données, par exemple le type "User
", le type "Group
" ou le type "Cluster
". En principe, on doit pouvoir effectuer des actions CRUD sur une Resource
.
Un Record
est une instance d'une Resource
. Par exemple le groupe "Binet Réseau" est un Record
de la Resource
"Group
".
Un Mapper
est un objet qui associe les Records
d'une Resource
aux objets en mémoire. C'est cet objet qui va nous permettre de définir des services pour gérer nos Resources
.
#DataStore
JSData fournit un outil qui permet de stocker les objets en mémoire cache, et donc d'éviter de faire des appels à l'API REST pour des objets déjà vus. Il s'agit du DataStore
.
Les Mappers
sont attachés à un DataStore
de telle sorte que tout appel à une ressource sur le serveur est mise en cache, de même que toute création d'une nouvelle instance d'une ressource.
Le service APIService
possède donc un attribut store
de type DataStore
. Par exemple, pour récupérer un utilisateur grace à son id, on utilisera l'instruction suivante :
APIService.store.find('user', 3)
Cette fonction renvoie un objet de type JSData.utils.Promise
. On peut donc utiliser la méthode .then()
pour exploiter le résultat.
#Classes, relations
##Définitions
Dans les fichiers du dossier src/shared/resources
sont définies les classes des objets de JS-Data. On peut voir que ces objets contiennent plus de champs que ceux fournis par le backend ; en effet, JS-Data permet de relier les objets entre eux. Par exemple, dans user.ts
on a :
hasMany: {
membership: {
foreignKey: 'user_id',
localField: 'memberships'
}
}
Grâce à cette relation, JS-Data va inclure dans user.memberships
tous les objets du Datastore de la classe Membership
tels que membership.user_di==user.id
. Réciproquement, dans membership.ts
:
belongsTo: {
user: {
localKey: 'user_id',
localField: 'user'
}
}
Dans le champ local membership.group
va figurer l'objet de la classe User
dont l'id est stocké dans le champ membership.user_id
.
##Utilisation
Ces liens entre objets s'utilisent d'une manière assez particulière. Cela se comprend mieux sur un exemple. Sur la page du profil d'un utilisateur, le composant ProfileDisplayComponent
qui reçoit en @Input
un objet de la classe User
va immédiatement chercher tous les Membership
s de cet user
. Lorsque ces Membership
s arrivent dans le DataStore
, ils sont liés directement et arrivent dans le champ user.memberships
. Chaque Membership
a un groupe membership.group
qui est automatiquement lié (grâce au champ membershipgroup_id
) mais pour qu'il soit lié au bon groupe il faut que ce groupe soit dans le DataStore. Ainsi il faut appeler store.find
pour chercher tous les groupes de l'utilisateur et les ramener dans le DataStore
. Le code suivant dans profile-display.ts
se comprend donc :
this.api.store.findAll('membership',{'user':this.user.id}).then(res => {
for (var membership of this.user.memberships) {
this.api.store.find('group',membership.group_id);
};
});
Dans profile-display.html
, on peut donc accéder aux groupes d'un utilisateur via user.memberships[...].group
.