如何定义一个 CoffeeScript 类,在第一次实例化时加载 jQuery,然后触发回调?
我对使用 JavaScript 的经典 OOP 还很陌生;这似乎是一个一般的 OOP 问题,但理想情况下我正在寻找使用 CoffeeScript 的实际代码示例来帮助我学习。
我想定义一个可以由任何其他函数/类实例化的类,但仅在第一次实例化时才执行其主要功能。直接的用例是一个可以由其他类调用的 LoadjQuery 类,该类动态处理加载 jQuery,但每个文档只能加载一次。首先实例化此类的代码可以提供选项和设置(jQuery 版本、缩小/开发版本和回调),但如果 jQuery 已加载,则实例化该类的任何其他尝试都将立即触发回调,或者等待它完成加载,然后触发回调。
这是我到目前为止编写的代码(有效但未经测试)。我不确定这是否是最优雅的方式。例如,有没有办法避免使用 @jquery_loading
标志和/或等待 jQuery 完成加载的 setInterval
?前者的存在只是为了防止代码被多次执行,这就是我想找到一种更自然的方法,而不是依赖于标志和条件分支。后者似乎不必要且尴尬,我想到了一种类似于 Google Analytics 的 _gaq
队列的方法(其中构建了待处理操作的队列,一旦 Google Analytics 库加载,它就会通过队列;然后立即处理队列中的后续添加),但我不知道如何实现它,并且可能不需要那么复杂。
# load jQuery dynamically (see: http://code.google.com/apis/libraries/devguide.html#jquery)
class LoadjQuery
@jquery_loading = false
@jquery_loaded = false
constructor: (callback, version = 1, compressed = true) ->
if @jquery_loading # only load once per document
if @jquery_loaded
callback()
else
check_jquery = ->
if @jquery_loaded
clearInterval check_jquery
callback()
setInterval check_jquery, 100
else
@jquery_loading = true # set flag
script = document.createElement 'script'
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/#{version}/jquery#{if compressed then '.min' else ''}.js"
script.onload = -> # set up event handler to ensure that jQuery is loaded before the callback is executed
if not @jquery_loaded
@jquery_loaded = true # set flag
callback()
script.onreadystatechange = -> # alternative event handler needed for Opera and IE
if not @jquery_loaded and (script.readyState is 'loaded' or script.readyState is 'complete')
@jquery_loaded = true # set flag
callback()
(document.getElementsByTagName('head') or document.getElementsByTagName 'body')[0].appendChild script
我正在寻找的可能是单身人士吗?如果是这样,最佳实践实现是什么(我见过几种不同的方法),您能给出一个代码示例吗?
谢谢!
I'm still pretty new to classical OOP using JavaScript; this seems like a general OOP question, but ideally I'm looking for an actual code example using CoffeeScript to help me learn.
I want to define a class that can be instantiated by any other function/class, but which executes its main functionality only the first time it's instantiated. The immediate use case will be a LoadjQuery
class that can be called by an other class, which handles loading jQuery dynamically, but only once per document. The code that instantiates this class first can provide options and settings (jQuery version, minified/dev version, and a callback), but any other attempts to instantiate the class will just fire the callback immediately if jQuery has already been loaded, or wait for it to finish loading, then fire the callback.
Here's the code that I've written so far (valid but untested). I'm not sure if this is the most elegant way. For example, is there a way to avoid having to use the @jquery_loading
flag, and/or the setInterval
that waits for jQuery to finish loading? The former only really exists to prevent the code from being executed more than once, which is what I'd like to find a more natural approach for rather than relying on a flag and a conditional branch. The latter seems unnecessary and awkward, and I have in mind an approach sort of like Google Analytics's _gaq
queue (where a queue of pending operations is built, and once the Google Analytics library has loaded, it works through the queue; subsequent additions to the queue are then processed immediately), but I don't know how to go about implementing that, and it may not need to be that sophisticated.
# load jQuery dynamically (see: http://code.google.com/apis/libraries/devguide.html#jquery)
class LoadjQuery
@jquery_loading = false
@jquery_loaded = false
constructor: (callback, version = 1, compressed = true) ->
if @jquery_loading # only load once per document
if @jquery_loaded
callback()
else
check_jquery = ->
if @jquery_loaded
clearInterval check_jquery
callback()
setInterval check_jquery, 100
else
@jquery_loading = true # set flag
script = document.createElement 'script'
script.src = "http://ajax.googleapis.com/ajax/libs/jquery/#{version}/jquery#{if compressed then '.min' else ''}.js"
script.onload = -> # set up event handler to ensure that jQuery is loaded before the callback is executed
if not @jquery_loaded
@jquery_loaded = true # set flag
callback()
script.onreadystatechange = -> # alternative event handler needed for Opera and IE
if not @jquery_loaded and (script.readyState is 'loaded' or script.readyState is 'complete')
@jquery_loaded = true # set flag
callback()
(document.getElementsByTagName('head') or document.getElementsByTagName 'body')[0].appendChild script
Is it maybe a singleton that I'm looking for? If so, what's the best-practice implementation (I've seen several different approaches), and can you give a code example to start from?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你把事情搞得太复杂了。
既然您已经在使用他们的 CDN,为什么不使用 Google 的加载程序呢?
这是一个简单的加载器实现:
您可以使用它,因为
我遵循您的初始结构,但请记住,您不应该因为对象的副作用而实例化对象;最好有某种在内部使用它的工厂方法:
You're overcomplicating things.
Since you're already using their CDN, why not use Google's loader?
Here's a simple loader implementation:
You'd use this as
I'm following your initial structure, but bear in mind you shouldn't instantiate objects for their side effects; best to have some kind of factory method that uses it internally: