1

I have some code that I need to run only once, but I'm not sure where do that code belongs to (service? factory?)

This is the code:

socket.on('recv chat', function (data){
    $("#chat").append(
        "<b>&lt;" + data.nick + "&gt;</b>: " +
        data.texto +
        "<br>"
    );
});

As you can see from the code, it's just a basic chat-app. My whole webpage has a few tabs and one of those tabs is the chat-tab. If I put this code inside my chat's controller, it gets executed on each tab-switch, so when somebody sends a message, it gets appended a few times.

Where should I place it for it to be executed only once?

0

3 Answers 3

1

You say it should execute only once, but presumably what you actually want is just that it display the values. If so the obvious thing would be for the code to update the model and then use angular's data binding for the display. (A good rule of thumb in angular would be that anywhere except a directive that tries to manipulate the DOM is probably doing it wrong).

So, some untested code to put inside your controller might be:

socket.on('recv chat', function (data){
    $scope.apply(function() {
        $scope.nick = data.nick;
        $scope.texto = data.texto;
    });
});

And your html just has:

<div ng-show="nick"><b>&lt;{{nick}}&gt;</b>: {{texto}}</div>

I think you need to wrap the model updates in $scope.apply() otherwise the event won't be happening in the correct angular context.

Answer to your comment:

Is there a new socket within each new instance of the controller? If so there's no problem as the old event handler at worst updates the old model and should go away when the old socket goes away. If you're re-using the socket between controllers then I think you want to define a service to handle the socket and you can register the callback with the service.

Sign up to request clarification or add additional context in comments.

3 Comments

Ah, yes indeed. The DOM manipulation should be handled by Angular. Anyways, that's not the problem. You see, each time socket.on... is executed, it gets binded to the event recv chat. So, if that code gets triggered twice, it will show each received message twice. That's why I need to make Angular run that code once and only once.
I've updated my answer a bit. Does that help? If need be I can expand on the idea of putting the socket handling into a service.
Oh, I just found briantford.com/blog/angular-socket-io.html which is exactly what I wanted. Thank you :)
0
var stopWatch = $scope.$on('someEvent', function(){
 //some code here
 stopWatch();
});

3 Comments

"some code" will be executed only once. To execute this code you should throw event 'someEvent' - $scope.$emit('someEvent')
Well... that's pretty much useless, isn't it? The problem is still there. I need to fire 'someEvent' only once, and that's my real problem. Anyways, I made that work with a service.
You can fire 'someEvent' as many times as you want, but the code will be executed only once.
0

This is not the best solution but this is by far the best working solution i have came across. You need to remove the already registered even. Just add this line before you attach the events.

socket.removeAllListeners();

socket.on('recv chat', function (data){
    $("#chat").append(
        "<b>&lt;" + data.nick + "&gt;</b>: " +
        data.texto +
        "<br>"
    );
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.