2017-06-23 18 views
7

मैं प्लगइन इंजेक्शन करने में सक्षम काम के लिए एक नया ढांचा तैयार करने का एक तरीका समझने की कोशिश कर रहा हूं। विचार यह है कि प्रत्येक फ़ाइल को असीमित रूप से लोड किया जाना चाहिए।जावास्क्रिप्ट es5 async प्लगइन आर्किटेक्चर

<script id="target_root" src="assets/js/target/target.js" async="true"></script> 
<script> 
    var target = target || {}; 
    target.cmd = target.cmd || []; 

    target.cmd.push(function() { 
     target.loadPlugins([ 
      {"name": "root", "src": "assets/js/target/target.root.js"}, 
      {"name": "krux", "src": "assets/js/target/target.krux.js"} 
     ]).then(
      target.init([ 
       { 
        'plugin': 'root', 
        'opts': { 
         'foo': 'bar' 
        } 
       }, 
       { 
        'plugin': 'krux', 
        'opts': { 
         'foo': 'bar' 
        } 
       } 
      ]) 
     ) 
    }); 
</script> 

मैं इनलाइन कार्यों (डोम के अंदर) का उपयोग किया था के रूप में मैं एक कमांड क्यू जो लोड पर सभी धक्का दिया कार्यों आह्वान हैं का उपयोग करने के बारे में सोचा:

यहाँ कैसे मैं अपने प्लगइन्स कॉन्फ़िगर करने के लिए प्यार होता है (डीएफपी के googletag cmd की तरह थोड़ा)।

जैसा कि कहा गया है कि प्रत्येक प्लगइन को असीमित रूप से लोड किया जाएगा, इसलिए उनमें से प्रत्येक का प्रारंभ तब ही शुरू होना चाहिए जब उनमें से सभी लोड हो जाएं (इसलिए तब() फ़ंक्शन)।

var target = (function(root, w, d, c) { 
    var queueIndex = 0, 
     amountPluginsLoaded = 0, 
     pluginsLoaded = []; 

    root.cmd = { 
     'queue': root && root.cmd ? root.cmd : [], 
     'push': function(fn) { 
      this.queue.push(fn); 
      this.next(); 
     }, 
     'next': function() { 
      if (this.queue.length > 0) { 
       this.queue.shift()(); 
      } 
     } 
    }; 

    root.init = function(plugins) { 

    }; 

    root.loadPlugins = function(plugins) { 
     var i = 0, 
      len = plugins.length; 
     for(; i < len; i++) { 
      _loadExternalJS(plugins[i]); 
     } 
    }; 

    function _loadExternalJS(plugin) { 
     var scriptRoot = d.getElementById('target_root'), 
      scriptElement = d.createElement('script'); 

     scriptElement.setAttribute('type', 'text/javascript'); 
     scriptElement.setAttribute('async', 'true'); 
     scriptElement.onload = function() { 
      amountPluginsLoaded++; 
      pluginsLoaded.push(plugin.name); 
     }; 
     scriptElement.setAttribute('src', plugin.src); 
     scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling); 
    } 

    function _initPlugin(plugin) { 

    } 

    for (; queueIndex < root.cmd.queue.length; queueIndex++) { 
     root.cmd.next(); 
    } 
}(target || {}, window, document, console)); 

यहाँ आप बुनियादी cmd कार्यक्षमता जो अधिरोहित किया जाएगा और लिपियों में से प्रत्येक के लोड हो रहा है है:

यहाँ आप मेरी स्क्रिप्ट है।

मुझे यह नहीं लगता कि मुझे तब तक आग लगाना है()। मुझे लगता है कि आप इसके अधिभार ईवेंट में _loadExternalJS() में इसका ट्रैक रखेंगे (जैसा कि आप कोड में देख सकते हैं)। लेकिन बस एक जोड़ना (राशिप्लगिन लोडेड === प्लगइन्सलोडेड। लम्बाई) {आग सभी inits} अनुत्पादक लगता है और कुछ ऐसा नहीं है जो फ़ंक्शन में संबंधित है। यही कारण है कि मैं कुछ() सुविधा को लागू करना पसंद करूंगा।

कोई विचार/राय?

उत्तर

0

मैं मान्य उत्तर प्राप्त नहीं किया था के रूप में, मैं अपने अनुत्पादक विचार :(

function _loadExternalJS(elem) { 
    var scriptRoot = d.getElementById('target_root'), 
     scriptElement = d.createElement('script'), 
     isElemPlugin = elem.isPlugin || typeof elem.isPlugin === "undefined", 
     loadAsync = elem.async || typeof elem.async === "undefined"; 

    scriptElement.setAttribute('type', 'text/javascript'); 
    scriptElement.setAttribute('async', loadAsync); 

    if (isElemPlugin) { 
     scriptElement.onload = function() { 
      jsLoaded++; 
     }; 
    } 

    scriptElement.setAttribute('src', elem.src); 
    scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling); 
} 

"फिर" कार्यक्षमता के बारे में सोच रहा उन लोगों के लिए ले लिया है, मैं मैंने निम्नलिखित किया है:

target.init = function (plugins) { 
    //do something 

    return { 
     'then': _then 
    } 
}; 

function _then(fn) { 
    var loaded; 
    loaded = w.setInterval(function() { 
     if (jsLoaded === pluginList.length) { 
      w.clearInterval(loaded); 
      fn(); 
     } 
    }, 10); 
} 

यदि कोई ओ एफ आपके पास एक बेहतर विचार है, कृपया पोस्ट करें !!!! :)

2

आप promise और promise.all का उपयोग कर सकते हैं ताकि वे सभी लोड हो जाएं।

root.loadPlugins = function(plugins) { 
    var promiseArray = plugins.map(function(plugin){ 
     return _loadExternalJS(plugin); 
    }); 
    return Promise.all(promiseArray); 
}; 

function _loadExternalJS(plugin) { 
    return new Promise((resolve, reject) => { 
     var scriptRoot = d.getElementById('target_root'), 
      scriptElement = d.createElement('script'); 

     scriptElement.setAttribute('type', 'text/javascript'); 
     scriptElement.setAttribute('async', 'true'); 
     scriptElement.onload = function() { 
      amountPluginsLoaded++; 
      pluginsLoaded.push(plugin.name); 
      resolve(plugin.name); 
     }; 
     scriptElement.setAttribute('src', plugin.src); 
     scriptRoot.parentNode.insertBefore(scriptElement, scriptRoot.nextSibling); 
    }); 
} 

तो

root.loadPlugins().then(function(){ 
    //initialize plugins 
}); 
+0

क्षमा करें लेकिन ईएस 5 के पास वादे नहीं थे। – Goowik

+0

हाँ और ब्लूबर्ड या क्यू लाइब्रेरी है। – fingerpich

+0

कार्य किसी भी बाहरी पुस्तकालय (प्रदर्शन, अनुरोध की राशि, अद्यतन मुद्दों, ...) के उपयोग की अनुमति नहीं देता है :( – Goowik

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