2014-02-02 2 views
2

common_tempaltes файл не является файлом requirejs, а скорее файлом, который определяет глобальную переменную.requirejs race condition - как заблокировать до получения предыдущего файла

common_templateshogan. они оба запрашиваются более или менее одновременно, но состояние гонки влияет. common_templates иногда выигрывает, поэтому код выходит из строя, а «hogan еще не загружен».

require(['module1', 'hogan', 'common_templates'], function(Module){ 
    Module.do_stuff() // this module also requires hogan and common_templates to be loaded 
}); 

кроме вложенные требуют, есть встроенный способ сказать, требует, чтобы блокировать до hogan полностью загружена?

вложенная:

require(['hogan'], function(Fn, Ui){ 
    require(['common_templates'], function(){ 
     require(['module1'], function(Module){ 
      Module.do_stuff(); 
     }); 
    }); 
}); 

Такой подход кажется немного Hacky. есть ли встроенный способ обойти эти условия гонки?

+0

Мое подозрение на этот провал заключается в том, что где-то есть какая-то круговая зависимость. Как вы думаете, вы могли бы также публиковать инструкции define для «hogan» и «common_templates»? – Katana314

+0

Его не круговая зависимость - ее состояние гонки. Круговая зависимость будет неустойчивой, а не прерывистой. Он также потерпит неудачу в тот момент, когда я получаю доступ к 'do_stuff' с сообщением ~", не может получить доступ к атрибуту undefined ". Я также вижу его состояние гонки на сетевой панели. – rikAtee

+0

Вы должны объяснить в своем вопросе, что содержит 'common_templates'. Вы получили два ответа на одно и то же: мой (после удаления) и jax's. Если вы не измените свой вопрос, чтобы предоставить более подробную информацию, вы будете получать тот же ответ. – Louis

ответ

4

Если common_templates не модуль AMD (не содержит define([deps]) вызова), то вам необходимо настроить его в качестве прокладки:

require.config({ 
    shims: { 
    common_templates: { 
     deps: ["hogan"] 
    } 
    } 
}); 

Теперь require(['module1', 'hogan', 'common_templates']) и require(['module1', 'common_templates']) должны работать.

+0

спасибо, но в соответствии с документами «[deps] не блокирует любые другие вызовы require() от запуска своих запросов на модули, это всего лишь способ указать некоторые модули для асинхронной загрузки как часть блока конфигурации». – rikAtee

+0

будет «блокировать» зависимые запросы. Например. в этом случае он гарантирует, что «common_templates» загружается только после завершения загрузки «hogan». В вашем случае, если вы хотите, чтобы 'module1' загружался только после загрузки' common_templates', вам нужно указать 'common_templates' в качестве зависимости в модуле1 или в гнезде, например' require (["common_templates"], function() {require (["module1"]);}) ' – Karolis

-1

Это не имеет смысла, вы сказали «common_templates требует Хогана», но если common_templates требует hogan то hogan уже будет загружен при запуске common_templates кода.

Убедитесь common_templates.js определяется следующим образом:

define(['hogan'], function(){ 
    //common_templates suff here 
}); 
+0

Да, это ответ, который я дал (который я удалил). Это имеет смысл дать этот ответ. Тем не менее, это комментарий, который я получил от автора вопроса: «common_templates не является файлом requirejs, а скорее файлом, определяющим глобальный объект». – Louis

+0

извините за недоразумение - «требует» было плохим словом для использования в вопросе с участием requirejs. Я обновил вопрос. – rikAtee

0

У меня была такая же проблема. Мне нужно было существенно «заблокировать» мой поток программ, чтобы убедиться, что начальный список зависимостей загружен перед вторым списком зависимостей, а затем, наконец, мой основной код приложения.Вот как я решил это. Это Require.js называют я сделал в моем файле index.html:

<script src="/js/lib/require_2.1.22.js"></script> 
<script> 
    //debugger; 
    //Load common code that includes config, then load the app 
    //logic for this page. Do the requirejs calls here instead of 
    //a separate file so after a build there are only 2 HTTP 
    //requests instead of three. 
    requirejs(['/js/common_libs.js'], function (common) { 
     //debugger; 
     //Ensure the the AdminLTE code and its dependencies get loaded prior to loading the Backbone App. 
     requirejs(['/js/lib/adminlte.js'], function (common) { 
      //debugger; 
      //The main file for the Backbone.js application. 
      requirejs(['/js/app/main_app.js']); 
     }); 
    }); 
</script> 

Файл common_libs.js содержит requirejs.config({shim:...}) материал. Библиотека adminlte.js делает свою собственную проверку зависимостей и будет жаловаться на консоль, если она не обнаружит ее зависимости. Моя проблема заключалась в том, что он загружался асинхронно с его зависимостями и вызывал состояние гонки.

я был в состоянии обернуть существующий код в adminlte.js так:

//My experiments with Require.js to prevent race conditions. 
define([ 
    'jQuery-2.1.4.min', 
    'bootstrap.3.3.6', 
    'jquery.slimscroll.min' 
], function($, Bootstrap, SlimScroll) { 

    //Existing code goes here 
    ... 

    //I knew to return this value by looking at the AdminLTE code. Your mileage may vary. 
    return $.AdminLTE; 
}); 

Это позволило мне загрузить эту библиотеку отдельно с его зависимостями. Код в adminlte.js выполняется только после загрузки его зависимостей. Затем, и только после этого будет загружено main_app.js вместе со своими зависимостями.

Структурирование вашего кода таким образом позволяет вам явно загружать ваши зависимости в пакетах.


Редактирование для ясности:

Зависимости загружаются в несколько этапов. Чтобы прояснить приведенный выше пример:

На первом этапе загружаются библиотеки jQuery, Boostrap и SlimScroll, затем выполняется файл adminlte.js.

На втором этапе загружаются все другие зависимости, затем выполняется файл main_app.js. main_app.js будет иметь свою собственную определенную ([], ...) функцию, которая вызывает остальные зависимости, которые она будет загружена.

Это гораздо эффективнее, чем запись вложенного вызова require() для каждой зависимости. И, насколько я могу судить по сайту requirejs.org, это «правильный» способ загрузки последовательных зависимостей.


Coding Обновление: Я также должен был обернуть код в jquery.slimscroll библиотеке внутри определения() заявление для того, чтобы явно крикнуть, что эта библиотека зависит от JQuery. В противном случае это создавало еще один шанс в гонке.

+0

Как это отличается от вложенного подхода, показанного в вопросе? – Louis

+0

Я отредактировал свой ответ выше, чтобы уточнить. –

+0

Вложенный подход, указанный в вопросе, также загружает зависимости по этапам. – Louis

Смежные вопросы