Другое решение состоит в том, чтобы выполнить код через последовательный исполнитель 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
Хотя это очень старый вопрос, я бы хотел опубликовать решение, которое я сейчас использую. Надеюсь, это поможет кому-то в будущем. После использования некоторых разных подходов я придумал красивую диаграмму , написанную Джоном Папой
. Он предлагает использовать специальную службу 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
и разрешает необходимые данные. Теперь не нужно делать это каждый раз.
Позвольте мне показать вам мой подход. Там - рабочий плункер
Давайте будем иметь 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 и наследования вида ... все доступные в любом дочернем состоянии ...
Убедитесь, что все здесь .