Как определить класс CoffeeScript, который сначала загружает jQuery, а затем просто вызывает обратный вызов? - PullRequest
0 голосов
/ 01 октября 2011

Я все еще довольно новичок в классической ООП с использованием JavaScript;это кажется общим вопросом ООП, но в идеале я ищу фактический пример кода, использующий CoffeeScript, чтобы помочь мне учиться.

Я хочу определить класс, который может быть создан любой другой функцией / классом, нокоторый выполняет свою основную функциональность только в первый раз, когда он создан.Непосредственным вариантом использования будет класс LoadjQuery, который может вызываться другим классом, который обрабатывает загрузку jQuery динамически, но только один раз для каждого документа.Код, который вначале создает этот класс, может предоставить опции и настройки (версия jQuery, версия minified / dev и обратный вызов), но любые другие попытки создания экземпляра класса просто вызовут обратный вызов немедленно, если jQuery уже был загружен, или ожидаютчтобы завершить загрузку, затем запустите обратный вызов.

Вот код, который я написал до сих пор (действительный, но не проверенный).Я не уверен, что это самый элегантный способ.Например, есть ли способ избежать использования флага @jquery_loading и / или setInterval, ожидающего завершения загрузки jQuery?Первый действительно существует только для предотвращения выполнения кода более одного раза, и это то, что я хотел бы найти более естественный подход, чем полагаться на флаг и условную ветвь.Последнее кажется ненужным и неуклюжим, и я имею в виду такой подход, как очередь _gaq в Google Analytics (где создается очередь ожидающих операций, и после загрузки библиотеки 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

Может быть, я синглтон?находясь в поиске?Если да, то какова реализация наилучшей практики (я видел несколько разных подходов), и можете ли вы привести пример кода для начала?

Спасибо!

1 Ответ

3 голосов
/ 01 октября 2011

Вы слишком усложняете вещи.

Поскольку вы уже используете их CDN, почему бы не использовать загрузчик Google?

<script type="text/javascript" src="https://www.google.com/jsapi?key=INSERT-YOUR-KEY"></script>
<script type="text/coffeescript">
google.load "jquery", "1.6.4"
</script>

Вот простая реализация загрузчика:

# load scripts dynamically
class ScriptLoader

    libraries =
        jQuery: "http://ajax.googleapis.com/ajax/libs/jquery/$version/jquery.js"

    constructor: (options..., callback) ->

        [lib, version, compressed] = options
        if @libraries[lib] then lib = @libraries[lib]

        loadCallback = =>
            return if @loaded
            @loaded = true
            callback()

        s = document.createElement 'script'
        s.onload = loadCallback
        s.onreadystatechange = ->
            loadCallback() if /loaded|complete/.test(s.readyState)

        s.src = lib.replace('$version', version)
        if compressed then lib = lib.replace('.js', '.min.js')

        (document.getElementsByTagName('head')?[0] or document.body).appendChild s

Вы бы использовали это как

new ScriptLoader 'jQuery', '1.6', -> alert window.jQuery

Я следую вашей исходной структуре, но имейте в виду, что вы не должны создавать экземпляры объектов для их побочных эффектов;лучше всего иметь какой-то фабричный метод, который использует его внутри:

loadScript 'jQuery', '1.6', -> ...
# or
ScriptLoader.load 'jQuery', -> ...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...