0

我正在和其他几个人一起构建一个小型 Web 应用程序。我想让其他开发人员定义几个在文档准备好时总是调用的函数。

我们的应用程序将以下脚本插入到每个页面的 HTML 正文中:

<script type="text/javascript">
  (function(){
    window.Utils = {
      funcs: {}
    };

    $(document).ready(function(){
      alert('Calling funcs...');

      var startFunc = Utils.funcs['start'];
      if (startFunc != undefined){
        startFunc();
      }

      var finishFunc = Utils.funcs['finish'];
      if (finishFunc != undefined){
        finishFunc();
      }
    });
  })();
</script>

然后,在一个单独的 .js 文件中,开发人员应该能够执行以下操作:

Utils.funcs['start'] = function(){
    alert('Starting...');
};

Utils.funcs['finish'] = function(){
    alert('Finishing...');
};

但这不起作用。这些函数永远不会被调用?

jsFiddle 链接:http: //jsfiddle.net/XvQtF/

4

3 回答 3

3

jsFiddle (非常令人惊讶)的默认设置是将您的代码放入window load处理程序中。(你可以在顶部的左侧看到这个,第二个下拉框显示“onload”。)这发生在加载过程的很晚,很久之后ready。因此,在您尝试运行它们之前不会添加这些功能。

如果其他开发人员在您定义元素之后将他们的功能Utils.funcs放入元素中但不等待事件,那很好:更新的小提琴scriptUtilsload


不过,对于它的价值,我倾向于使用 pub/sub 解决方案而不是单个函数。例如,如果您想拥有多个start功能,那么您当前的结构不允许这样做。

jQuery has Deferredand Promisenow,可以用于此。下面是一个简单的例子:Live Copy | 直播源

<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<meta charset=utf-8 />
<title>Pub/Sub with Deferred and Promise</title>
</head>
<body>
  <script>
    (function($) {
      // Deferred objects for our app states
      var start = new $.Deferred(),
          finish = new $.Deferred();

      window.Utils = {
        start: start.promise(),   // Only expose the Promise of each
        finish: finish.promise()  // " " " " " "
      };

      $(function() {
        alert("Calling funcs...");

        // Start the app
        start.resolve();

        // Finish the app (or whatever)
        finish.resolve();
      });

    })(jQuery);
  </script>
  <script>
    // Module 1
    Utils.start.then(function() {
      alert("Module 1 Started!");
    });
    Utils.finish.then(function() {
      alert("Module 1 Finished!");
    });
  </script>
  <script>
    // Module 2
    Utils.start.then(function() {
      alert("Module 2 Started!");
    });
    Utils.finish.then(function() {
      alert("Module 2 Finished!");
    });
  </script>
</body>
</html>
于 2013-07-14T10:26:01.320 回答
0

在单独的脚本中设置 Utils 以作为第一个加载。此外,无条件地执行此操作(不在任何回调等中):

/* load as first script, sets up a global container-object for later use */
var Utils = {
  funcs: {}
}

请注意,可以在全局范围内定义全局变量。

/* other script */
(function(){
  function myFunc() { /*...*/ };

  // now store a reference in Utils
  Utils.funcs.start = myFunc;
})();

如另一个答案中所述:注意各种脚本/代码的加载和调用顺序:

$(document).ready 本质上是大多数浏览器(但 IE 的早期版本)的“DOMContentLoaded”事件。"DOMContentLoaded" 当所有最初在 head-section 中找到的 inline-resources 都已加载并且 body 的 DOM 结构存在时触发。由于这不包括任何注入的内容,因此可能会在任何模块化库(通过注入脚本标签加载模块)完全加载并呈现之前触发该事件。(鉴于这些脚本仅使用浏览器提供的少数网络插槽/套接字同时加载图像和其他内联内容,它们可能是整个加载过程中最后准备好的事情之一。)

于 2013-07-14T10:57:33.023 回答
0

而不是仅仅使用

 startFunc() and 
 finishFunc() 

尝试使用这个

 startFunc.apply(this, null) and 
 finishFunc.apply(this, null)

这将调用函数。

还要确保

 Utils.funcs['start']
 Utils.funcs['finish'] 

在调用它们之前被初始化。

于 2013-07-14T12:12:25.370 回答