2012-04-27 67 views
0

我有一個客戶端JS應用程序需要加載模板來顯示每個項目。假設他們是筆記。異步模板加載 - 如何只加載一次?

問題出在異步部分。我無法讓模板只加載一次。每當筆記呼叫render函數時,它就會加載。

下面是一些代碼:

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) 
     }) 
    } 
} 

所以在這種情況下,它會加載模板的三倍,即使有檢查,以防止這一點。我想這是因爲三個模板直接進入其他模塊,但我怎麼能夠防止這種情況呢?

我不想使用sync ajax加載,因爲這會凍結瀏覽器。

編輯:最後,我用@ Managu的解決方案稍作修改。

而不是使用自己的循環,我用以下,更優雅:

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

'.lodaTemplate'如何知道要加載的模板? – Esailija 2012-04-27 22:50:40

+0

因爲現在只有一個模板需要在這個應用中加載。 – 2012-04-27 22:51:31

回答

1

也許保持工作積壓的需要,一旦模板被加載辦?基本上是一個隊列來平滑由異步造成的阻抗不匹配。

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

這不會改變模板將被加載多次的事實。當第二個音符來到這個函數時,由於'template'仍然是空的,它會發出另一個請求來獲取模板... – 2012-04-27 22:59:43

+0

@FlorianMargaine。是的,你是對的。修正了。 – Managu 2012-04-27 23:00:51

+0

哦,好的!讓我嘗試一下,回到你身邊:)不是很優雅的東西:( – 2012-04-27 23:01:50

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

    loadTemplate = function() { 
     return promise; 
    }; 

    return promise; 
}; 

請注意,在這裏不需要jQuery的,我只是寫的僞代碼。您可以使用任何提供延期的庫。

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

非常優雅:) – 2012-04-27 23:04:25

0

「我不想使用sync ajax加載,因爲這會凍結瀏覽器。」

如果您嘗試使用jQuery來執行此操作,sync ajax將只凍結瀏覽器。 Frame.js旨在解決您遇到的問題。 Frame有多種方法可以解決這個問題,但它們都涉及一定數量的同步和異步混合。可能是最簡單的方法是:

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(); 
}); 

如果你不知道的模板是什麼,它可能是相同的或者每個音符不同的,那麼你可以這樣做,而不是:

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(); 
    }); 
}); 

那會加載模板同步,但顯示更新異步。

+0

它看起來像Frame.js只是另一個延期庫:)。這確實回答了這個問題,但@Esailija已經提出了這個問題。感謝您的努力! – 2012-04-27 23:33:41