2012-02-03 10 views
5

मैं पूरी तरह से यहाँ कुछ गायब हो सकता है, लेकिन मैं निम्नलिखित है:संग्रह बनाने के बाद फ़ंक्शन चलाने के लिए backbone.js प्राप्त करना?

  • एक मॉडल है जो 'सभी' डेटा समाहित (सभी JSON एक URL से भरी हुई)
  • मॉडल एक (या अधिक) है संग्रह जो यह डेटा यह निर्माण
  • कुछ कोड है जो मैं जब डेटा आरंभ नहीं हो जाता संग्रह पर चलाना चाहते हैं और लोड

मेरा प्रश्न रचना संग्रह के बारे में है पर मिल गया के साथ instantiating है। मैं इसे संग्रह के दायरे से बाहर कर सकता था, लेकिन मैं इसे बल्कि encapsulate करना होगा (अन्यथा यह एक प्रारंभिक आदि के साथ 'वर्ग' बनाने का मुद्दा क्या है)।

  1. मैं मैं initialize() समारोह में उस कोड डाल सकता है सोचा था, लेकिन वह चलाता है से पहले मॉडल भर जाने के बाद, तो मैं मॉडल है कि संग्रह शामिल (this.models खाली है) करने के लिए पहुँच नहीं है।

  2. तब मैंने सोचा कि मैं किसी ईवेंट से जुड़ सकता हूं, लेकिन शुरुआत के बाद कोई भी ईवेंट ट्रिगर नहीं हुआ है। वे होंगे अगर मैंने fetch के साथ अपने स्वयं के अंतराल से संग्रह लोड किया है, लेकिन मैं ऐसा नहीं कर रहा हूं, मैं संग्रह को पूर्व-मौजूदा डेटा से प्रारंभ कर रहा हूं।

मेरा प्रश्न: कैसे संग्रह पर चलाने के लिए तुरंत बाद यह डेटा के साथ आरंभ नहीं हो जाता कोड को प्रारंभ प्राप्त करने के लिए (अर्थात this.models खाली नहीं है)।

क्या यह 'बाहरी' कोड शामिल किए बिना ऐसा करना संभव है?

ठीक है यहाँ डेमो कोड है, शायद यह चीजों को बेहतर समझाएगा।

var Everything = Backbone.Model.extend({ 
    url: "/static/data/mydata.json", 
    parse: function(data) 
    { 
     this.set("things", new Things(data.things, {controller: this})); 
    } 
}); 

var Thing = Backbone.Model.extend({ 
}); 

var Things = Backbone.Collection.extend({ 
    model: Thing, 
    initialize: function(data, options) 
    { 
     // HERE I want access to this.models. 
     // Unfortunately it has not yet been populated. 
     console.log("initialize"); 
     console.log(this.models); 
     // result: [] 

     // And this event never gets triggered either! 
     this.on("all", function(eventType) 
     { 
      console.log("Some kind of event happend!", eventType); 
     }); 
    } 
}); 

var everything = new Everything(); 
everything.fetch(); 

// Some manual poking to prove that the demo code above works: 

// Run after everything has happened, to prove collection does get created with data 
setTimeout(function(){console.log("outside data", everything.get("things").models);}, 1000); 
// This has the expected result, prints a load of models. 


// Prove that the event hander works. 
setTimeout(function(){console.log("outside trigger", everything.get("things").trigger("change"));}, 1000); 
// This triggers the event callback. 

उत्तर

7

दुर्भाग्य से आप के लिए संग्रह डेटा के बाद ही इसे ठीक से पहले प्रारंभ किया गया था और मॉडल silent: true झंडा जिसका मतलब है कि घटना को ट्रिगर नहीं करेगा उपयोग करके उसे रीसेट कर रहे हैं के साथ सेट हो जाता है।

यदि आप वास्तव में इसका उपयोग करना चाहते हैं तो आप सेटटाइमआउट (..., 0) या अंडरस्कोर defer विधि का उपयोग कर अगले ब्राउज़र ईवेंट लूप पर जो भी करना चाहते हैं उसे निष्पादित करने में देरी कर सकते हैं।

initialize: function(data, options) { 

    _.defer(_.bind(this.doSomething, this)); 
}, 

doSomething: function() { 

    // now the models are going to be available 
} 
+0

मैं संकलन के निर्माण को समकालिक रूप से करने की उम्मीद कर रहा था (उदाहरण के लिए, इसका उपयोग 'Everything.parse' की अगली पंक्ति पर किया जा सकता है)। स्पष्ट रूप से स्थगित ऐसा नहीं करेंगे। मुझे संग्रह से तर्क को बाहर ले जाना पड़ सकता है। Backbone.js को एक परिवर्तन अनुरोध शायद ... – Joe

+0

'defer' का उपयोग करना आदर्श हो जाता है यदि आप EventCistener की वेबकैम में स्थापित करना चाहते हैं। वेबसीजीएम आरेख एक स्वतंत्र वस्तु के रूप में भरा हुआ है - और जीवन को बेवकूफ तस्वीर के रूप में शुरू करता है। आपको घटनाओं को भेजने शुरू करने के लिए आपको स्पष्ट रूप से यह बताना होगा - जिसे आप रीढ़ की हड्डी के बुनियादी ढांचे में वापस पाइप कर सकते हैं। मुझे संदेह है कि उसी तकनीक का इस्तेमाल अन्य प्लग-इन (एसवीजी/पीडीएफ इत्यादि) के साथ बातचीत करने के लिए किया जा सकता है, जिनमें से कई ब्रोसर में अच्छी तरह से खेल नहीं सकते हैं। –

0

यह एक पुराना प्रश्न खोदना। मुझे एक ही समस्या थी, और इस समाधान को बनाने में कुछ मदद मिली:

सेट फ़ंक्शन को विस्तारित करके हम जान सकते हैं कि संग्रह का डेटा वास्तविक मॉडल में कब परिवर्तित किया गया है। (सेट को .add और .reset से बुलाया जाता है, जिसका अर्थ यह है कि इसे फ़ंक्शन क्लास को तुरंत चालू करने और संग्रह से reset या set पर ले जाने के मूल समारोह के दौरान कहा जाता है। रीढ़ की हड्डी में एनोटेटेड स्रोत में एक गोताखोरी और फ़ंक्शन प्रवाह के बाद यहां मदद मिली)

इस तरह हम निष्पादन प्रवाह को हैक किए बिना कब/कैसे अधिसूचित हो सकते हैं, इस पर नियंत्रण कर सकते हैं।

var MyCollection = Backbone.Collection.extend({ 
    url: "http://private-a2993-test958.apiary-mock.com/notes", 
    initialize: function() { 
    this.listenToOnce(this, 'set', this.onInitialized) 
    }, 

    onInitialized:function(){ 
    console.log("collection models have been initialized:",this.models) 
    }, 

    set: function(models,options){ 
    Backbone.Collection.prototype.set.call(this, models, options); 
    this.trigger("set"); 
    } 
}) 

//Works with Fetch! 
var fetchCollection= new MyCollection() 
fetchCollection.fetch(); 

//Works with initializing data 
var colData = new MyCollection([ 
     {id:5, name:'five'}, 
     {id:6, name:'six'}, 
     {id:7, name:'seven'}, 
     {id:8, name:'eight'} 
    ]) 

//doesn't trigger the initialized function 
colData.add(new Backbone.Model({id:9,name:'nine'}; 

नोट: हम .listenToOnce का उपयोग न हो, तो हम भी onInitialized हर बार एक मॉडल के रूप में अच्छी तरह से करने के लिए जोड़ा या संग्रह में परिवर्तित हो जाता है कहा जाता है मिल जाएगा।

संबंधित मुद्दे