角度异步调用 [英] Angular async calls
问题描述
我的 Angular 应用程序中发生了一个奇怪的问题,我认为原因是 Angular 的异步性,但我不确定如何解决它.
I have a bizarre issue happening in my Angular app and I think the async'ness of Angular is the cause but I'm not sure how I can fix it.
在 .run
我有以下内容:
app.run(function ($user, $soundcloud) {
$user.set();
$soundcloud.set();
});
然后是两个服务...
app.service('$user', ['$http', function ($http) {
var currentUser;
this.set = function () {
$http.get('/users/active/profile')
.success(function (obj) {
currentUser = obj;
})
.error(function () {
console.log('ERR');
})
}
this.fetch = function () {
return currentUser;
}
}]);
app.service('$soundcloud', ['$http', function ($http) {
var sc;
this.set = function () {
$http.get('/users/active/services/soundcloud')
.success(function (obj) {
sc = obj;
})
.error(function () {
console.log('Error fetching soundcloud feed')
})
}
this.fetch = function () {
return sc;
}
}]);
<小时>
我遇到的问题是,当我转到/profile 并重新加载页面时,除非我将 $soundcloud.fetch() 包装在 中,否则从 $soundcloud.fetch() 返回的数据不可用setTimeout()
函数显然不理想,所以我想知道我应该将 $soundcloud.set()
放在哪里,以便在页面加载时立即提供这些数据.
The issue I'm having is that when I go to /profile and reload the page, the data returned from $soundcloud.fetch() isn't available unless I wrap $soundcloud.fetch() inside a setTimeout()
function which obviously isn't ideal so I'm wondering where I should place $soundcloud.set()
to also make that data available immediately on page load.
这是我目前的控制器:
app.controller('profileController', ['$scope', '$user', '$soundcloud', function ($scope, $user, $soundcloud) {
$scope.activeUser = $user.fetch();
$scope.activeSoundcloud = $soundcloud.fetch();
console.log($user.fetch());
setTimeout(function () {
console.log($soundcloud.fetch());
},100);
}]);
如果我将 $soundcloud.fetch()
放在 setTimeout 之外,那么我会得到 undefined
作为结果.应该在何处调用 $soundcloud.set/fetch 以使两组数据(用户和声音云)立即可用?
If I take $soundcloud.fetch()
outside of the setTimeout then I get undefined
as the result. Where should $soundcloud.set/fetch be called in order to make both sets of data (user and soundcloud) immediately available?
推荐答案
解决这个问题的一种方法是获取所有必要的数据,然后手动引导应用程序.
One way to solve this problem is to fetch all the necessary data and then manually bootstrap the application.
为此,创建bootstrapper.js
.您可以访问内置的 angular 服务,而无需通过 angular.injector(['ng']).invoke()
引导模块,它接受一个可以注入依赖项的函数.urlMap
变量只是设置的键值存储及其各自的 url.您通过 angular.forEach()
循环这个 urlMap
,然后一个一个地获取所有设置,并将每个设置与每个设置一起存储在 settings
变量中其各自的键.将每个 $http
承诺请求存储在 promises
数组中,以使用 $q.all()
解决它.当所有 promise 都得到解决后,调用 bootstrap()
函数,该函数在 app.settings
模块中添加一个 Settings
值,然后手动引导应用程序.
To do this, create bootstrapper.js
. You can access the built-in angular services without bootstrapping a module by angular.injector(['ng']).invoke()
which accepts a function with dependencies that can be injected. The urlMap
variable is simply a key value store for the settings together with each of its respective urls. You loop this urlMap
via angular.forEach()
and then get all settings one by one and store each settings in a settings
variable along with each of its respective keys. Store each $http
promise request in promises
array to resolve it with $q.all()
. When all promises have been resolved, call bootstrap()
function which adds a Settings
value in app.settings
module and then manually bootstraps the application.
bootstrapper.js
angular.injector(['ng']).invoke(function($http, $q) {
var urlMap = {
$user: '/users/active/profile',
$soundcloud: '/users/active/services/soundcloud'
};
var settings = {};
var promises = [];
var appConfig = angular.module('app.settings', []);
angular.forEach(urlMap, function(url, key) {
promises.push($http.get(url).success(function(data) {
settings[key] = data;
}));
});
$q.all(promises).then(function() {
bootstrap(settings);
}).catch(function() {
bootstrap();
});
function bootstrap(settings) {
appConfig.value('Settings', settings);
angular.element(document).ready(function() {
angular.bootstrap(document, ['app', 'app.settings']);
});
}
});
app.js
angular.module('app', [])
.run(function(Settings) {
if(Settings === null) {
// go to login page or
// a page that will display an
// error if any of the requested
// settings failed
}
})
.controller('ProfileController', function($scope, Settings) {
console.log(Settings);
});
这篇关于角度异步调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!