2017-06-27 3 views
1

J'ai une page simple "auteurs" qui montre une liste d'auteurs.Ember.js 2. Lazy fetch en arrière-plan après le rendu de la page

Chaque auteur a bien sûr beaucoup de livres , mais dans cette page (et dans l'API) Je ne montre pas (/include) toutes les données de livre.

Dans la voie des auteurs que j'ai le modèle par défaut():

model() { 
    return this.store.findAll('author'); 
} 

et tout est OK.

Maintenant je besoin quelque chose que paresseux chercher (en arrière-plan ) des données d'API d'autres (ceux des livres).

Mais je ne veux pas que cet appel bloque le rendu de ma page d'auteur. Donc, j'ai la valeur par défaut et rapide beforeModel(), model() et afterModel() sans aucune récupération (sauf pour les données des auteurs).

SEULEMENT après page est rendu, je besoin de quelque chose (peut-être un service?) qui appelle « api/books?author:1,2,3,4,5... »

De cette façon, je l'ai déjà les livres dans mon « magasin » quand quelqu'un clique sur un Athor (pas de chargeur en attente dans cette page de livre).

Comment faire?

Répondre

1

1. Si vous voulez charger paresseusement et les données de la relation magasin sans bloquer l'interface utilisateur:

Si vous ne voulez pas afficher les données de relations paresseusement chargées (en hasMany -relationships spéciales), je recommande le faire dans la afterModel -hook:

route.js:

// ... 

    afterModel(authors) { 
    let lastPromise = new Promise(function(resolve) { resolve(); }); 
    authors.forEach(author => { 
     lastPromise = lastPromise.then(() => { 
     return author.get('books'); 
     }); 
    }); 
    }, 

    // ...   

2. Si vous voulez charger paresseusement, les données relationnelles magasin et d'affichage sans bloc King UI:

Il y a plusieurs façons de le faire. Une façon que je préfère quand les données de chargement paresseux est la suivante:

D'abord, je crée un composant qui encapsule l'affichage et le chargement de mes données. Dans votre exemple, j'appellerais mon composant book-shelf.

Après avoir été inséré dans le DOM, mon composant veut afficher ses livres. Voir le code suivant.

component.js:

import Ember from 'ember'; 

const { 
    get, 
    computed, 
    ArrayProxy, 
    PromiseProxyMixin, 
    inject: { service } 
} = Ember; 

const ArrayPromiseProxy = ArrayProxy.extend(PromiseProxyMixin); 

export default Ember.Component.extend({ 
    // API: 
    author: null, 

    // Internal: 
    store: service(), 
    books: computed(
    'author.id', 
    function() { 
     if(!get(this, 'author.id')) { 
     return []; 
     } 
     return ArrayPromiseProxy.create({ 
     promise: get(this, 'store').query('book', { authorId: get(this, 'author.id') }) 
     }); 
    } 
), 
}); 

Et dans votre modèle .HBS:

<div class="book-shelf"> 
    {{#if books.isFulfilled}} 
    Books of {{author.name}}: 
    <ul> 
     {{#each books as |book|}} 
     <li>{{book.name}}</li> 
     {{/each}} 
    </ul> 
    {{else}} 
    Loading... please wait... 
    {{/if}} 
</div> 

Cette approche combine un proxy tableau avec un proxy promesse afin d'agir comme un tableau mais aussi fournir des informations si les données sont chargées.

Vous pouvez utiliser ce composant comme chaque composant ember.js:

{{book-shelf author=mySpecialAuthor}} 
+0

Merci beaucoup @Timm, mais je besoin de ce pas dans DOM, pas dans un composant. Dans la page des auteurs, j'ai besoin (seulement après le rendu de la page des auteurs) d'aller chercher en arrière-plan les données des livres. De cette façon, les données du livre de chaque auteur est prêt pour le clic sur n'importe quel auteur (et le rendu de la page du livre ...). –

+0

donc peut-être la nouvelle "première" solution ajoutée travaillera pour vous? – Timm