I have a case where app.run
sends a broadcast message to all controllers but before some of them actually loaded. And therefore they don't catch event.
我有一个案例,app.run向所有控制器发送广播消息,但在其中一些实际加载之前。因此他们没有抓住事件。
Here is an example:
这是一个例子:
app.run(function($rootScope){
// I get this event too fast and GroupsCtrl still not ready
ionic.Platform.ready(function(){
// notify controllers on device ready
$rootScope.$broadcast('notifyCtrlOnDeviceReady', device);
});
});
and controller:
app.controller('GroupsCtrl', function($rootScope,$scope){
$scope.$on('notifyCtrlOnDeviceReady', function(event, device){
alert('notifyCtrlOnDeviceReady - done');
});
});
-
I thought to create some flag in the service but it seems like a workaround.
我想在服务中创建一些标志,但它似乎是一种解决方法。
-
I also thought to create a
$watch
that listens on a service flag and sends a broadcast when all controllers finished initialization.我还想创建一个监听服务标志的$ watch,并在所有控制器完成初始化后发送广播。
Is there more elegant way to notify controllers when they have loaded?
是否有更优雅的方式在加载时通知控制器?
Thanks,
2 个解决方案
#1
10
As I see it you have two options here. I would not suggest using the $broadcast event system in this instance due to your issue where controllers may/ may not have been loaded.
在我看来,你有两个选择。由于您可能/可能未加载控制器的问题,我不建议在此实例中使用$ broadcast事件系统。
1) You can put a promise on the rootscope and attach then statements in your controllers:
1)您可以在rootscope上放置一个promise并在控制器中附加then语句:
app.run(function($rootScope, $q){
var dfd = $q.defer();
$rootScope.deviceReady = dfd.promise;
ionic.Platform.ready(function(){
dfd.resolve( device );
});
});
app.controller('GroupsCtrl', function($rootScope, $scope){
$rootScope.deviceReady.then(function( device ){
//do something with device
})
});
2) If your platform allow multiple ready functions to be registered just add it to each controller which should be run immediately if the device is ready.
2)如果您的平台允许注册多个就绪功能,只需将其添加到每个控制器,如果设备准备就应立即运行。
app.controller('GroupsCtrl', function($rootScope, $scope){
ionic.Platform.ready(function(){
//do something with device here.
});
});
Personally I would go with #2 if possible as it keeps the $rootScope cleaner, but either way should do fine. You may even try putting your ionic.Platform ready in a service and registering that, so if the API ever changes the controllers will not have to be modified later down the road.
就个人而言,如果可能,我会选择#2,因为它保持$ rootScope更清洁,但无论哪种方式都应该做得很好。您甚至可以尝试将ionic.Platform准备好投入使用并注册,因此如果API发生变化,控制器将不会在以后的路上进行修改。
app.factory("ionicPlatform"), function( $q ){
var ready = $q.defered();
ionic.Platform.ready(function( device ){
ready.resolve( device );
});
return {
ready: ready.promise
}
});
app.controller('GroupsCtrl', function($scope, ionicPlatform){
ionicPlatform.ready.then(function(device){
//do something with device here.
});
});
#2
1
I think your situation is similar to this SO question (but not a duplicate) where they want to ensure a given controller is loaded first.
我认为你的情况类似于这个问题(但不是重复)他们想要确保首先加载给定的控制器。
The answer there suggested avoiding "invisible" dependencies, and I think needing all the controllers loaded would be one.
那里的答案建议避免“隐形”依赖,我认为需要加载的所有控制器都是一个。
I would suggest having a service that has both a flag and a promise function. Controllers can check the flag, and if it's not true, they call the function (maybe WaitForLoaded()
and can have a then
block ready to handle things. The set for the flag then resolves
the promise, and that is only set from your app.run
block.
我建议有一个既有标志又有保证功能的服务。控制器可以检查标志,如果不是真的,他们会调用该函数(可能是WaitForLoaded()并且可以使用then块来处理事情。该标志的集合然后解析了promise,并且只能从你的app设置.run块。
#1
10
As I see it you have two options here. I would not suggest using the $broadcast event system in this instance due to your issue where controllers may/ may not have been loaded.
在我看来,你有两个选择。由于您可能/可能未加载控制器的问题,我不建议在此实例中使用$ broadcast事件系统。
1) You can put a promise on the rootscope and attach then statements in your controllers:
1)您可以在rootscope上放置一个promise并在控制器中附加then语句:
app.run(function($rootScope, $q){
var dfd = $q.defer();
$rootScope.deviceReady = dfd.promise;
ionic.Platform.ready(function(){
dfd.resolve( device );
});
});
app.controller('GroupsCtrl', function($rootScope, $scope){
$rootScope.deviceReady.then(function( device ){
//do something with device
})
});
2) If your platform allow multiple ready functions to be registered just add it to each controller which should be run immediately if the device is ready.
2)如果您的平台允许注册多个就绪功能,只需将其添加到每个控制器,如果设备准备就应立即运行。
app.controller('GroupsCtrl', function($rootScope, $scope){
ionic.Platform.ready(function(){
//do something with device here.
});
});
Personally I would go with #2 if possible as it keeps the $rootScope cleaner, but either way should do fine. You may even try putting your ionic.Platform ready in a service and registering that, so if the API ever changes the controllers will not have to be modified later down the road.
就个人而言,如果可能,我会选择#2,因为它保持$ rootScope更清洁,但无论哪种方式都应该做得很好。您甚至可以尝试将ionic.Platform准备好投入使用并注册,因此如果API发生变化,控制器将不会在以后的路上进行修改。
app.factory("ionicPlatform"), function( $q ){
var ready = $q.defered();
ionic.Platform.ready(function( device ){
ready.resolve( device );
});
return {
ready: ready.promise
}
});
app.controller('GroupsCtrl', function($scope, ionicPlatform){
ionicPlatform.ready.then(function(device){
//do something with device here.
});
});
#2
1
I think your situation is similar to this SO question (but not a duplicate) where they want to ensure a given controller is loaded first.
我认为你的情况类似于这个问题(但不是重复)他们想要确保首先加载给定的控制器。
The answer there suggested avoiding "invisible" dependencies, and I think needing all the controllers loaded would be one.
那里的答案建议避免“隐形”依赖,我认为需要加载的所有控制器都是一个。
I would suggest having a service that has both a flag and a promise function. Controllers can check the flag, and if it's not true, they call the function (maybe WaitForLoaded()
and can have a then
block ready to handle things. The set for the flag then resolves
the promise, and that is only set from your app.run
block.
我建议有一个既有标志又有保证功能的服务。控制器可以检查标志,如果不是真的,他们会调用该函数(可能是WaitForLoaded()并且可以使用then块来处理事情。该标志的集合然后解析了promise,并且只能从你的app设置.run块。