jQuery 延迟的 AJAX 调用返回值



我有一个函数,它将返回缓存的模板,或者如果模板尚未缓存 - 它将通过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);
});

最新更新