好的,终于想出了如何做到这一点。口头上,您要做的是将所有对加载程序的调用排队,然后一次处理一个。在以下代码点,从队列中拉出一个调用来处理它:
- 在第一次调用插件之后
- 异步调用完成后
- 每次通过返回缓存值来避免异步调用。
这是任何可能需要示例的人的代码
/**
* RequireJS plugin for loading templates cross domain via easyXDM
* Author: Larry Gerndt
* Version: 0.0.1 (2013/5/1)
* Usage: html!url,fragment-selector
* url: omit the .html extension
* fragment-selector: css selector of the fragment to extract
*/
define(['assetLoader','jquery'], function(AssetLoader, $) {
/**
* Caches documents and fragments of documents
* The hash is derived from everything following the bang (!)
* For example, given this: html!assets/templates/IntroductionTooltip/introduction-tooltip,#mint-itt, we just
* strip out all illegal characters using the _hash() function and that's our hash for fragments. But we also
* want to cache the document from which the fragment came, in case a request is made for a different fragment from
* the same document. The hash for the document cache is made the same way as for fragments, except first omitting
* everything from the comma to the end of the line. In other words, omitting the fragment selector.
*/
function Cache(name) {
this.name = name;
this.cache = {};
this.size = 0;
}
Cache.prototype = {
get: function(name) {
return this.cache[name];
},
has: function(name) {
return this.cache.hasOwnProperty(name);
},
add: function(name, html) {
this.cache[name] = html;
this.size += 1;
}
};
//-----------------------------------------------------------------------------------------------------------
// a FIFO queue that stores calls to this module
//-----------------------------------------------------------------------------------------------------------
function CallQueue() {
this.store = [];
}
CallQueue.prototype = {
push: function(name, req, onLoad, config) {
this.store.push({
name : name,
req : req,
onLoad: onLoad,
config: config
});
},
pop: function() {
return this.store.length ? this.store.splice(this.store.length - 1, 1)[0] : null;
},
isEmpty: function() {
return this.store.length === 0;
}
};
var documentCache = new Cache('document'),
fragmentCache = new Cache('fragment'),
callQueue = new CallQueue(),
processedFirstCall = false;
//-----------------------------------------------------------------------------------------------------------
// helpers
//-----------------------------------------------------------------------------------------------------------
function getFragment(html, fragmentSelector) {
var $container, fragmentHtml;
if (!document.getElementById('mint-html-container')) {
$('body').append('<div id="mint-html-container" style="display:none;"></div>');
}
$('#mint-html-container').html(html);
fragmentHtml = $(fragmentSelector).get(0).outerHTML;
return fragmentHtml;
}
function hash(string) {
return string.replace(/[\/,#\.\s\-]/g, '');
}
function loadRemoteAsset(url, fragmentSelector, onLoad) {
var documentHash = hash(url),
fragmentHash = hash(url+fragmentSelector);
AssetLoader.loadHtmlFragment(url + '.html', fragmentSelector).then(function(fragmentHtml, allHtml) {
documentCache.add(documentHash, allHtml);
fragmentCache.add(fragmentHash, fragmentHtml);
onLoad(fragmentHtml);
processOneCall();
}, function() {
onLoad.error('AssetLoader: failed for unknown reason');
});
}
function processOneCall() {
if (!callQueue.isEmpty()) {
var item = callQueue.pop(),
split = item.name.split(','),
url = split[0],
fragmentSelector = split[1];
if (url.indexOf('/') === 0) {
url = item.config.baseUrl + url;
}
if (!url || !fragmentSelector) {
item.onLoad.error('AssetLoader: invalid argument: ' + item.name + '\n Example Usage: html!assets/templates/IntroductionTooltip/introduction-tooltip,#mint-itt');
}
else {
var documentHash = hash(url),
fragmentHash = hash(url+fragmentSelector);
if (fragmentCache.has(fragmentHash)) {
item.onLoad(fragmentCache.get(fragmentHash));
//console.log('using cached fragment for url: ', url, ', fragment: ', fragmentSelector);
processOneCall();
}
else if (documentCache.has(documentHash)) {
var fragmentHtml = getFragment(documentCache.get(documentHash), fragmentSelector);
fragmentCache.add(fragmentHash, fragmentHtml);
item.onLoad(fragmentHtml);
//console.log('using cached document for url: ',url, ', fragment: ', fragmentSelector);
processOneCall();
}
else {
loadRemoteAsset(url, fragmentSelector, item.onLoad);
}
}
}
}
//-----------------------------------------------------------------------------------------------------------
// public API
//-----------------------------------------------------------------------------------------------------------
return {
load : function(name, req, onload, config){
callQueue.push(name, req, onload, config);
if (!processedFirstCall) {
processedFirstCall = true;
processOneCall();
}
},
pluginBuilder: 'html-builder' // uses this no-op module during Optimizer build to avoid error "window is not defined"
};
});