2012-04-27 1 views
0

J'ai une application JS côté client qui doit charger un modèle pour afficher chaque élément. Disons que ce sont des notes.Chargement du gabarit asynchrone - Comment charger une seule fois?

Le problème est dans la partie asynchrone. Je ne peux pas faire en sorte que le modèle ne soit chargé qu'une seule fois. Il se charge chaque fois qu'une note appelle la fonction render.

Voici un code:

var notes = [ {}, {}, {} ] // Some Note objects 
notes.forEach(function(note) { 
    render(note) 
} 

// Have some variable to hold the template 
var template 

// Now on the render function 
function render(note) { 

    // First, if the template exists, go straight to the next function 
    if (template) { 

     // The display function takes care of appending the note 
     // to the body after applying datas on the template 
     display(note) 
    } 
    else { 
     // loadTemplate just loads the template in an ajax request 
     // and executes the callback with the template as argument 
     loadTemplate(function(data) { 

      // I fill in the template variable 
      template = data 

      // And I display the note since the template is available 
      display(note) 
     }) 
    } 
} 

Donc, dans ce cas, il va charger trois fois le modèle, bien qu'il y ait un contrôle pour empêcher cela. Je suppose que c'est parce que les trois modèles vont directement dans l'autre, mais comment puis-je empêcher cela?

Je ne veux pas utiliser le chargement sync ajax car cela gèlera le navigateur.

Édition: à la fin, j'ai utilisé la solution @ Managu, légèrement modifiée.

Au lieu d'utiliser sa boucle, je l'ai utilisé ce qui suit, beaucoup plus élégante:

while (backlog.length) { 
    display(backlog.shift()) 
} 
+0

Comment '.lodaTemplate' sait-il quel modèle charger? – Esailija

+0

Parce qu'il n'y a qu'un seul modèle à charger pour le moment dans cette application. –

Répondre

1

Peut-être garder un arriéré de travail qui doit être fait une fois que le modèle est chargé? Fondamentalement, une file d'attente pour lisser sur la différence d'impédance causée par l'asynchronie.

var template; 
var backlog; 

function render(note) 
{ 
    if (template) { 
     // Template already loaded, just display. 
     display(note); 
    } else if (backlog) { 
     // Template being loaded, push work onto backlog. 
     backlog.push(note); 
    } else { 
     // Template not being loaded yet. Create backlog queue and launch request 
     // to load template. 
     backlog=[note]; 
     loadTemplate(function(loaded_template) { 
      // Template finally came over the wire. Save it, and then 
      // work off the backlog. 
      template = loaded_template; 
      for (var note=backlog.shift(); 
       backlog.length!=0; 
       note=backlog.shift()) 
      { 
       display(note); 
      } 
     }); 
    } 
} 
+0

Cela ne changera pas le fait que le modèle sera chargé plus d'une fois. Lorsque la deuxième note arrive à la fonction, puisque 'template' est encore vide, il va faire une autre requête pour obtenir le template ... –

+0

@FlorianMargaine. Ouais, tu as raison. Corrigé cela. – Managu

+0

Oh, gentil! Laissez-moi essayer cela et revenir à vous :) Pas très élégant tho :( –

2
var loadTemplate = function() { 
    var promise = $.get("/"); 

    loadTemplate = function() { 
     return promise; 
    }; 

    return promise; 
}; 

Notez que jQuery n'est pas nécessaire ici, je vous écris comme pseudocode. Vous pouvez utiliser n'importe quelle bibliothèque qui fournit des reports.

loadTemplate().then(function(data) { 

    // I fill in the template variable 
    template = data 

    // And I display the note since the template is available 
    display(note) 
}) 
+0

Très élégant :) –

0

"Je ne souhaite pas utiliser le chargement sync ajax car cela gèle le navigateur." Sync ajax ne fera que geler le navigateur si vous essayez d'utiliser jQuery pour le faire. Frame.js a été conçu pour résoudre les problèmes exactement comme vous l'avez. Il existe plusieurs façons de résoudre ce problème avec Frame, mais elles impliquent toutes une certaine quantité de synchronisation et de mélange asynchrone. Probablement la meilleure façon serait:

Frame(function(next){ 
    loadTemplate(next); 
}); 
Frame(function(next, data){ // data here is the value passed to loadTemplate's callback 
    notes.forEach(function(note) { 
     template = data; 
     display(note); 
    }); 
    next(); 
}); 

Si vous n'êtes pas sûr de ce que le modèle est et il pourrait être identiques ou différents pour chaque note, vous pouvez le faire à la place:

notes.forEach(function(note) { 
    Frame(function(next){ 
     loadTemplate(note.templateName, next); // next here is a callback to advance to the next Frame 
    }); 
    Frame(function(next, template){ 
     display(note, template); 
     next(); 
    }); 
}); 

Ce chargerait les modèles de synchronisation, mais faire l'affichage de mise à jour asynchrone.

+0

On dirait que Frame.js est juste une autre bibliothèque différée :). Cela répond à la question, mais @Esailija l'a déjà proposé. Merci pour l'effort tho! –

Questions connexes