如何在“完成”回调中取消承诺?

时间:2014-04-21 19:46:55

标签: jquery promise jquery-deferred cancellation

我有以下情况......

$.when(
    $.getScript('script.js')
).done(function () {
    if ( scriptIsAlreadyLoaded ) {
        // I want to cancel this promise.
        // I no longer want script.js because
        // it has already been loaded in another
        // instance.
    }

    // I dont' want this to run if the above
    // condition is true.
    doStuff();
});

我理解在done()内执行此操作并没有多大意义,因为根据定义,取消承诺为时已晚。

那么这里最好的方法是什么?

  

注意:此代码段可以多次执行。这就是我想避免多次加载脚本的原因。

1 个答案:

答案 0 :(得分:1)

取消.done()处理程序中的promise是没有意义的。当调用.done()处理程序时,操作已经完成(听起来可能你已经知道了)。因此,当调用.done()处理程序时,脚本的加载已经完成。没有什么可以取消的。

如果您只是想阻止自己的代码尝试多次加载脚本,那么您实际上并没有使用promises。您可以只跟踪自己的标志,也可以测试环境以查看脚本是否已存在。例如,您可以使用此函数检查是否已加载以特定文件名结尾的脚本标记:

function isScriptPresent(fname) {
    var regex = new RegExp(fname + "$");
    var scripts = document.getElementsByTagName("script");
    for (var i = 0; i < scripts.length; i++) {
        if (regex.test(scripts[i].src)) {
            return true;
        }
    }
    return false;
}

if (!isScriptPresent("script.js")) {
    $.getScript("script.js");
}

或者,您可以创建自己的getScript函数,首先检查它是否已经加载:

$.getScriptIfNotLoaded = function(fname) {
    if (!isScriptPresent(fname)) {
        return $.getScript(fname);
    }
}

然后,您可以这样做:

$.getScriptIfNotLoaded("script.js");

并且,它永远不会在同一页面中多次加载。这样做的好处是,首先加载脚本的方式并不重要(即使它是在原始HTML中) - 如果它已经在页面中,它会找到它。


您还可以跟踪地图中已加载的内容:

(function() {
    var loadedScripts = {};

    $.loadScriptOnce = function(fname) {
        if (!loadedScripts[fname]) {
            loadedScripts[fname] = true;
            return $.getScript(fname);
        }
    };
})();

$.loadScriptOnce("scripts.js");