Angularjs разрешает обещание для всех состояний в ui router [duplicate]

Другое решение состоит в том, чтобы выполнить код через последовательный исполнитель nsynjs .

Если базовая функция многозначна

nsynjs будет последовательно оценивать все обещания и ставить обещания результат в свойство data:

function synchronousCode() {

    var getURL = function(url) {
        return window.fetch(url).data.text().data;
    };
    
    var url = 'https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js';
    console.log('received bytes:',getURL(url).length);
    
};

nsynjs.run(synchronousCode,{},function(){
    console.log('synchronousCode done');
});

Если базовая функция не обещает

Шаг 1. Wrap с обратным вызовом в оболочку, совместимую с nsynjs (если у нее есть обещанная версия, вы можете пропустить этот тест):

var ajaxGet = function (ctx,url) {
    var res = {};
    var ex;
    $.ajax(url)
    .done(function (data) {
        res.data = data;
    })
    .fail(function(e) {
        ex = e;
    })
    .always(function() {
        ctx.resume(ex);
    });
    return res;
};
ajaxGet.nsynjsHasCallback = true;

Шаг 2. Вставить синхронную логику в функцию:

function process() {
    console.log('got data:', ajaxGet(nsynjsCtx, "data/file1.json").data);
}

Шаг 3. Выполнить функцию синхронно через nnsynjs:

nsynjs.run(process,this,function () {
    console.log("synchronous function finished");
});

Nsynjs будет оценивать все операторы и выражения шаг за шагом, приостанавливая выполнение в случае, если результат некоторой медленной функции не готов.

Дополнительные примеры здесь: https://github.com/amaksr/nsynjs/tree/master/examples

14
задан Sray 30 January 2015 в 16:42
поделиться

2 ответа

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

. Он предлагает использовать специальную службу routerHelperProvider и настраивать состояния как обычный объект JS. Я не собираюсь копировать весь провайдер здесь. Подробнее см. Ссылку выше. Но я покажу, как я решил свою проблему с помощью этой службы.

Вот часть кода этого провайдера, который берет объект JS и преобразует его в конфигурацию состояний:

function configureStates(states, otherwisePath) {
    states.forEach(function(state) {
        $stateProvider.state(state.state, state.config);
});

Я преобразовал его следующим образом:

function configureStates(states, otherwisePath) {

    states.forEach(function(state) {

        var resolveAlways = {

            translations: ['Translations', function(Translations) {

                if (state.translationCategory) {

                    return Translations.get(state.translationCategory);

                } else {

                    return {};

                }

            }],

        };  



        state.config.resolve =

            angular.extend(state.config.resolve || {}, resolveAlways || {});



        $stateProvider.state(state.state, state.config);

    }); 

}); 

И мой объект настройки маршрута теперь выглядит следующим образом:

        {
            state: ‘users’,
            translationsCategory: ‘users’,
            config: {
                controller: ‘usersController’
                controllerAs: ‘vm’,
                url: ‘/users’.
                templateUrl: ‘users.html'
            }

Итак, что я сделал:

Я реализовал объект resolveAlways, который принимает пользовательское свойство translationsCategory, внедряет службу Translations и разрешает необходимые данные. Теперь не нужно делать это каждый раз.

7
ответ дан Sray 25 August 2018 в 06:51
поделиться

Позвольте мне показать вам мой подход. Там - рабочий плункер

Давайте будем иметь translation.json следующим образом:

{
  "home" : "trans for home",
  "parent" : "trans for parent",
  "parent.child" : "trans for child"
}

Теперь давайте представим супер родительское состояние root

$stateProvider
  .state('root', {
    abstract: true,
    template: '<div ui-view=""></div>',
    resolve: ['Translations'
      , function(Translations){return Translations.loadAll();}]
  });

Это супер-корневое состояние не имеет url (не влияет на какой-либо дочерний url) . Теперь мы будем тихо вводить это в каждое состояние:

$stateProvider
  .state('home', {
      parent: 'root',
      url: "/home",
      templateUrl: 'tpl.html',
  })
  .state('parent', {
      parent: 'root',
      url: "/parent",
      templateUrl: 'tpl.html',
  })

Как мы видим, мы используем установку parent - и не влияем / не расширяем исходное состояние name .

Корневое состояние загружает переводы одним выстрелом с помощью нового метода loadAll():

.service('Translations', ['$http'
    ,function($http) {
    translationsService = {
      data : {},
      loadAll : function(){
        return $http
          .get("translations.json")  
          .then(function(response){
            this.data = response.data;    
            return this.data;
          })
      },
      get: function(section) {
        return data[section];
      }
    };

    return translationsService;
}])

Нам совсем не нужно $q. Наше супер-корневое состояние просто решает, что однажды ... с помощью методов $http и loadAll(). Все они теперь загружены, и мы можем даже разместить эту службу в $rootScope:

.run(['$rootScope', '$state', '$stateParams', 'Translations',
  function ($rootScope, $state, $stateParams, Translations) {
    $rootScope.$state = $state;
    $rootScope.$stateParams = $stateParams;
    $rootScope.Translations = Translations;
}])

И мы можем получить к ней доступ к ней:

<h5>Translation</h5>
<pre>{{Translations.get($state.current.name) | json}}</pre>

Ничего себе ... это решение, приносящее выгоду почти из каждой функции, идущей с UI-Router ... Я бы сказал. Все загружены один раз. Все унаследованы из-за $ rootScope и наследования вида ... все доступные в любом дочернем состоянии ...

Убедитесь, что все здесь .

25
ответ дан Aᴍɪʀ 25 August 2018 в 06:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: