如何管理JavaScript中的依赖关系?

4
我有一些脚本需要在运行之前等待特定条件的满足,例如等待其他脚本加载或等待数据对象创建。

我该如何管理这些依赖关系?我能想到的唯一方法是使用setTimeout以短时间间隔循环并检查函数或对象的存在。有更好的方法吗?

如果setTimeout是唯一的选择,那么合理的轮询页面时间间隔是多少?50毫秒、100毫秒?

[编辑]我的一些脚本收集数据,可以来自页面本身或Web服务,有时来自多个源的组合。数据可以随时准备好,在页面加载之前或之后。其他脚本呈现数据(例如构建图表)。

[更新]感谢有用的答案。我同意我不应该重复造轮子,但如果我使用一个库,至少我想了解其背后的逻辑(它只是一个花哨的超时吗?)以尝试并预测对我的页面的性能影响。


请查看LAB.js或其他类似的脚本加载器。 - Pointy
setTimeout 不是你最好的选择,你能提供更多细节吗?为什么你不能启动正在加载的脚本? - Khodor
脚本需要满足几个条件:数据必须存在且函数必须加载。它不仅依赖于另一个脚本。 - Christophe
4个回答

2
在加载脚本的末尾,你可以使用类似 loaded(xyz); 的函数调用。这个函数在其他地方定义,并设置为根据 xyz 的值调用已注册的回调函数。 xyz 可以是任何内容,一个简单的字符串来标识脚本,或一个复杂的对象或函数等。
或者只需使用jQuery.getScript(url [, success(data, textStatus)] )

1
对于相互依赖的脚本,可以使用类似于RequireJS的模块系统。
对于远程加载数据,可以使用回调函数,例如。
$.get("/some/data", "json").then(function (data) {
    // now i've got my data; no polling needed.
});

以下是这两者的一个例子:

// renderer.js
define(function (require, exports, module) {
    exports.render = function (data, element) {
        // obviously more sophisticated in the real world.
        element.innerText = JSON.stringify(data);
    };
});

// main.js
define(function (require, exports, module) {
    var renderer = require("./renderer");

    $(function () {
        var elToRenderInto = document.getElementById("#render-here");

        $("#fetch-and-render-button").on("click", function () {
            $.get("/some/data", "json").then(function (data) {
                renderer.render(data, elToRenderTo);
            });
        });
    });
});

谢谢,这很有道理。在我的情况下,问题是我可以控制消耗函数和数据的脚本,而不是加载它们的脚本。这就是我在编辑中试图解释的内容。 - Christophe
哦,如果你没有控制权,那么你就完了,我想轮询是唯一能想到的选择。也许这些脚本可以给你提供某种钩子?例如,触发一个自定义事件,你可以订阅它。 - Domenic
我实际上在这里发布了一个关于脚本onload的问题http://stackoverflow.com/questions/8956414/cross-browser-onload-event-in-a-static-script-tag。+1感谢您提供有关jQuery deferred/then的信息。 - Christophe

1

有许多框架可用于此类事情。

我目前正在使用Backbone http://documentcloud.github.com/backbone/

朋友们也推荐了knockout.js http://knockoutjs.com/

这两个框架都使用MVC模式,在模型加载数据后更新视图

[更新] 我认为在它们最基本的层面上,这些库使用回调函数和事件监听器来更新页面的各个部分。

例如:

model1.loadData = function(){
    $.get('http://example.com/model1', function(response){
        this.save(response);
        this.emit('change');
    });
}

model1.bind('change',view1.update);
model1.bind('change',view2.update);

谢谢!这看起来就是我要找的。你觉得这样的框架也能监控脚本何时被加载,还是我需要将它们与其他回复中提到的库结合使用? - Christophe

0

我使用过pxLoader,一个JavaScript预加载器,它的效果非常好。默认情况下,它使用100毫秒轮询。

除非你需要一些非常定制化的东西,否则我不会费力去重新发明轮子,所以看看那个(或任何JavaScript预加载库)吧。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接