我有一个函数,它将返回缓存的模板,或者如果模板尚未缓存 - 它将通过AJAX加载它,然后返回它。这是我得到的:
var getTpl = function( name ) {
var cached = cache.get( 'templates' ) || {};
if( cached.hasOwnProperty( name ) ) {
console.log( 'template ' + name + '.mustache found in cache' );
return cached[ name ];
}
else {
console.log( 'requesting ' + name + '.mustache template via AJAX' );
var tpl;
$.ajax( {
url: path.templates + '/' + name + '.mustache',
async: false,
success: function( data ) {
tpl = data;
var cached = store.get( 'miniTemplates' ) || {};
var newTemplate = {};
newTemplate[ name ] = data;
if( ! cached.hasOwnProperty( name ) ) cache.set( 'templates', _.extend( cached, newTemplate ) )
},
error: function() { tpl = false; }
} );
return tpl;
}
}
这工作正常。但是,Chrome抱怨:
Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check http://xhr.spec.whatwg.org/.
因此,我想改用$.deferred
,但我无法理解它。如何重写上面的函数,以便调用getTpl
将始终返回模板(形成缓存或直接从 AJAX 请求返回)?
您可以使用承诺/延期概念来实现您的需求
var getTpl = function( name ) {
var promise;
var cached = cache.get( 'templates' ) || {};
if( cached.hasOwnProperty( name ) ) {
console.log( 'template ' + name + '.mustache found in cache' );
var df = new $.Deferred();
df.resolve(cached[ name ]);
promise = df.promise();
} else {
console.log( 'requesting ' + name + '.mustache template via AJAX' );
promise = $.ajax({
url: path.templates + '/' + name + '.mustache'
}).then(function(data) {
tpl = data;
var cached = store.get( 'miniTemplates' ) || {};
var newTemplate = {};
newTemplate[ name ] = data;
if( ! cached.hasOwnProperty( name ) ) cache.set( 'templates', _.extend( cached, newTemplate ) )
return tpl;
});
}
return promise;
}
然后,像这样调用你的方法:
getTpl('xyz')
.then(function(template) {
// you have the template, either from cache or fetched via ajax
})
.fail(function(err) {
console.log(err);
});
由于您似乎已经在使用下划线/lodash,因此您可以使用记忆而不是维护自己的缓存。
承诺的美妙之处在于,你可以一次又一次地访问它们,它们将始终产生相同的价值:
var getTpl = _.memoize(function( name ) {
console.log( 'requesting ' + name + '.mustache template via AJAX' );
return $.ajax({
url: path.templates + '/' + name + '.mustache'
});
});
是的,真的就是这么简单。
然后你可以像任何其他承诺一样使用它:
getTpl('myTemplate').then(function (template) {
// use template
}, function (error) {
console.log('Could not retrieve template.', error);
});