ExtJs 5.0.1: Synchronus Ajax-запрос в Firefox

В проекте у нас есть одиночный объект конфигурации, который содержит конфигурацию, полученную с сервера (ServerConfig). Он определяется как

Ext.define('SI.ServerConfig', {
    singleton: true,
    constructor: function () {
        this.callParent(arguments);

        // Closure which holds the serverConfig after the synchronus request
        var serverConfig;

        Ext.Ajax.request({
            url: 'example.de/getConfig.php',
            method: 'POST',
            async: false,
            success: function(response){
                var responseObj = Ext.JSON.decode(response.responseText);
                serverConfig = responseObj.serverConfig;
            }
        });

        //definition of setter/getter function for the serverConfig closure
        this.get = function (optionName, defaultVal) {
            if (Ext.isDefined(serverConfig[optionName])){
                return serverConfig[optionName];
            }

            return defaultVal;
        };


        this.set = function (optionName, value) {
            serverConfig[optionName] = value;
        };
    }
});

В конструкторе у нас есть замыкание, которое сохраняется после синхронного Ajax-запроса объекта конфигурации сервера. Нам нужно сделать запрос на синхронизацию, потому что значения конфигурации сервера необходимы в различных других классах, чтобы обеспечить создание конфигурации перед созданием. С помощью функции установки и получения мы предоставляем доступ к определенным в ней значениям. В каждом контроллере/представлении/модели нам нужен доступ к конфигурации сервера, нам требуется синглтон.

Ext.define('SI.view.TestView', {
    extends: 'Ext.panel.Panel',
    requires: ['SI.ServerConfig'],

    // This fails most of the time in Firefox, but works every time in Chrome and IE 8+
    title: SI.ServerConfig.get('testTitle')
});

Но когда мы обращаемся к синглтону в объекте конфигурации в определении класса, синглетон конфигурации сервера не создается в Firefox все время. В Chrome и в Internet Explorer 8+ он работает должным образом.

Итак, чтобы убедиться, что у нас есть синглтон, готовый к использованию, мы попробовали следующее. Мы переместили определение приложения в обратный вызов Ext.require. Но это не исправляет это для Firefox.

Ext.require([
    'SI.ServerConfig'
], function () {
    Ext.define('SI.Application', {
      // ....
    }); /
}); 

В отладчике Firefox регистрируется следующее:

Synchrone XMLHttpRequests am Haupt-Thread sollte nicht mehr verwendet werden, 
weil es nachteilige Effekte für das Erlebnis der Endbenutzer hat.
Für weitere Hilfe siehe http://xhr.spec.whatwg.org/

Из спецификации XHR:

Synchronous XMLHttpRequest outside of workers is in the process of being 
removed from the web platform as it has detrimental effects to the end 
user's experience. (This is a long process that takes many years.) 

Developers must not pass false for the async argument when the JavaScript 
global environment is a document environment. User agents are strongly 
encouraged to warn about such usage in developer tools and may experiment with 
throwing anInvalidAccessError exception when it occurs.

Таким образом, в будущем запросы на синхронизацию будут удалены и разрешены только для веб-воркеров. Нам нужно решение для этого.

Проблема возникает только в режиме разработчика, когда мы собираем его с помощью сборки приложения sencha, он работает в Firefox. ..

Спасибо за любые предложения. Энди

Обновить index.html -> index.php

Я изменил index.html на index.php, как предложил @colinramsay, и включил объект конфигурации сервера до включения микрозагрузчика. Теперь предупреждение о Synchrone XMLHttpRequests исчезло в Firefox.

Но проблема с доступом к синглтону в объекте конфигурации в определении класса по-прежнему остается для Firefox.


person And-y    schedule 05.12.2014    source источник


Ответы (2)


Другой совершенно другой подход заключается в изменении корневого index.html вашего приложения на index.php, который делает что-то вроде следующего:

<!DOCTYPE HTML>
<html manifest="">
    <head> 
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="UTF-8">

    <title></title>

    <script type="text/javascript">
        var SI = {};
        <?php
        echo 'SI.ServerConfig = { "testTitle": "some string" }'; 
        ?>
    </script>

    <!-- The line below must be kept intact for Sencha Cmd to build your application -->
    <script id="microloader" type="text/javascript" src="bootstrap.js"></script>

</head>
<body></body>
</html>

Это позволяет вам изменить код получения на что-то вроде:

function get(optionName, defaultVal) {
    if (Ext.isDefined(SI.ServerConfig[optionName])){
        return SI.ServerConfig[optionName];
    }

    return defaultVal;
}

Вы используете PHP для прямого вывода вашей конфигурации на HTML-страницу в виде JSON перед Ext JS и загрузкой вашего приложения.

person Colin Ramsay    schedule 08.12.2014
comment
Спасибо за этот подход, я попробую, если это сработает для нашего проекта. - person And-y; 08.12.2014

Попробуй это:

Ext.define('SI.view.TestView', {
    extends: 'Ext.panel.Panel',
    requires: ['SI.ServerConfig'],

    constructor: function() {
        this.callParent();
        this.setTitle(SI.ServerConfig.get('testTitle'));
    }
});

Я подозреваю, что это проблема порядка загрузки. В исходном коде Ext.define будет запускаться одновременно с SI.ServerConfig до того, как сработает запрос, поэтому SI.ServerConfig мог не загрузиться через запрос. Вызывая его в конструкторе, вы можете быть уверены, что все требования выполнены, и поэтому он должен быть доступен.

person Colin Ramsay    schedule 08.12.2014
comment
Да, мы думали об этом, но когда у нас есть компоненты с большим количеством элементов, и этим элементам также нужны некоторые значения из serverConfig, адаптировать этот код сложно. Также, когда синхронный флаг в xhr удален, у нас будет та же проблема, потому что сначала нам нужны данные в синглтоне serverConfig, а затем мы можем получить к ним доступ с помощью функции gettter/setter. - person And-y; 08.12.2014