简体   繁体   中英

Creating AngularJS object that calls method on app load

I am wondering if there is a convention within AngularJS for creating an object that lives within the app module, but is not attached directly to the view in any way, but is called when the view has loaded and the app starts up. In particular, I am trying to write an object that dispatches messages to listening controllers when they come in from the server.

Currently, I have implemented this by creating a "Controller" that attaches to the view. It has a monitor() function that is called when the page loads, and then listens in a loop for any incoming messages. I call the monitor() function from within the loaded view, by setting the ng-controller like so:

<div ng-controller="MyController">
{{ monitor() }}
</div>

This doesn't feel like the right thing to do. This "Controller" isn't interacting with the view in any way, so my gut tells me I am violating principles of AngularJS. But I haven't been able to turn up an easy solution that is endorsed by the AngularJS doc.

I am looking for a way to create an object that lives within the AngularJS world (in other words, it can use dependency injection to get access to services, and it can use $scope.$broadcast to send messages to other listening controllers), but that doesn't need to attach itself to the view in any way.

Ideally, I am looking for a way to say, "Here Angular, on startup, create this object, and run this method on it." Is there a way to do this?

You may use this as a starting point:

declaration of your object.

AngularJS: Service vs provider vs factory

myApp.factory('MessageBus', function() {
    return {
        listeners: [],
        init: function() {
            // do whatever you need at startup
        },
        pushMessage: function(msg) {
            angular.forEach(this.listeners, function(listener) {
                listener(msg);
            });
        },
        subscribe: function(onMessageCallback) {
            this.listeners.push(onMessageCallback);
        }
    };
});

calling a method on angular appilcation start

https://docs.angularjs.org/api/ng/type/angular.Module#run

myApp.run(function(MessageBus) {
     MessageBus.init();
});

using this object within controllers

https://docs.angularjs.org/guide/di

myApp.controller('MessageCtrl', function($scope, MessageBus) {
     $scope.messagesToShow = [];
     MessageBus.subscribe(function(message) {
          $scope.messagesToShow.push(message);
     });
     $scope.submitMessage = function(id, text) {
           MessageBus.pushMessage({
                type: 'TEXTMESSAGE',
                id: id,
                payload: text
           });
     };
});

Note that this is something to start with and nothing for any production code. For example the controller doesn't unsubscribe after being destroyed - if the page changes - and so you leak memory.

Don't use $broadcast-events for this

1: they are slow

2: if this MessageBus has a specific concern, than in should be an own object with a meaningfull name and api. Otherwise your $rootScope will be flooded with thousends of different events for different concerns when your application grows. A service is always easier to document and you have a clean dependency on that specific service. Only using events on the $rootScope hides this dependency from every developer reading and hopefully understanding your codebase,

Yeah you approach is really smelly. This function will be called every time a $apply/$digest invokes.

Maybe move the function into the run callback on the module.

var app = angular.module("YourApp", [//dependencies]);

app.run(function($YourUIService){
 $YourUIService.monitor();
});

The run will be invoked, when your angularjs-module has loaded every dependency and is ready to run.

Didn't find the doc for this :/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM