我正在重构一个资源加载函数,该函数使用传统的回调模式来代替使用jQuery Deferreds。

此函数采用网址数组,为每个资源创建一个新的Deferred对象,创建一个$.when Deferred对象以监视它们,并返回$.when对象的promise。

这是该方法的简化版本:

theLib = {
    getResources : function(paths) {
        var deferreds = [];
        theLib.isLoading = true;
        $.each(paths, function(i, path) {
            // do something with the path, either using getScript
            // or making a new $.Deferred as needed
            deferreds.push(/* the deferred object from above comment */);
        });
        theLib.currentDeferred = $.when.apply(null,deferreds).always(function() {
            theLib.isLoading = false;
        });

        return theLib.currentDeferred.promise();
};

这很好。

我的问题:在旧的脚本中,不仅会基于用户的操作或事件来调用theLib.getResources(),而且还会定义一个主资源列表,应用程序将在用户不执行任何操作(例如,读取文章)。

这些流资源中的某些资源与用户执行操作时可以手动调用的资源相同。该脚本足够聪明,不会通过跟踪加载的内容来两次加载资源。

它还跟踪theLib.isLoading。该函数的开始看起来像这样:
getResources : function(paths, callback) {
    if (theLib.isLoading) {
        settimeout(function() {
            theLib.getResources(paths, callback);
        }, 100);
    }
    theLib.isLoading = true;

我不能再这样做了,因为我需要返回一个Promise对象。

我知道我可以检查theLib.currentDeferred.isResolved()。到那时,如果无法解决:如何将更多的延迟对象添加到正在监视的$.when队列中?

最佳答案

我想我需要问这个问题才能为自己找到解决方案。基本上,我在getResources的开头添加了以下代码:
if ( ! theLib.currentDeferred.isResolved()) { return $.when(theLib.currentDeferred).always(function() { theLib.getResources(paths); }).promise(); }
以上失败。正确的解决方案是通过管道传递结果:

if ( ! theLib.currentDeferred.isResolved()) {
    return theLib.currentDeferred.pipe(function() {
        return theLib.getResources(paths);
    });
}

09-12 02:04