Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[frontend] How to handle arriving messages published to concrete channel #192

Open
aantipov opened this issue Jan 20, 2016 · 6 comments
Open

Comments

@aantipov
Copy link

Hi
I'm a frontend developer.
Backend sends a lot of messages published to different channels.
I can see from browser console the message arrived has channel property.
But the problem is a callback passed to swampdragon.onChannelMessage doesn't get that channel information. It gets strange channels list instead.
So when a message arrives I can't figure out the channel it was published to and therefore handle it properly.
I found the code where that channel info is stripped off https://github.com/jonashagstedt/swampdragon/blob/master/swampdragon/static/swampdragon/js/dist/swampdragon.js#L261

if ('channel' in e.data) {
  var channel = swampDragon.channels[e.data.channel];
  delete(e.data['channel']);
  swampDragon.settings.onchannelmessage(channel, e.data);
  return;
}

So my question is how to figure out what channel the message arrived was published to in order to be able to handle the message properly?

@AlexejStukov
Copy link

You should be able to access the channel information by using

swampdragon.onChannelMessage(function (channels, message) {
    for(var i in channels) {
        if (channels[i] == "your_channel") {
            // your code goes here
        }
    }
}

and "your_channel" is set by the swampdragon.subscribe("your_route", "your_channel", ...) function. Your backend developer sets "your_route" in the Router as route_name = "your_route". Hope that helps you out.

@aantipov
Copy link
Author

@AlexejStukov
A simple example: in my controller I have three subscriptions:

swampdragon.subscribe("my_route", "my_channel_1", ...)
swampdragon.subscribe("my_route", "my_channel_2", ...)
swampdragon.subscribe("my_route", "my_channel_3", ...)

then if I have the suggested solution:

swampdragon.onChannelMessage(function (channels, message) {
    for(var i in channels) {
        if (channels[i] == "my_channel_1") {
            callback_1();
        }
        if (channels[i] == "my_channel_2") {
           callback_2();
        }
        if (channels[i] == "my_channel_3") {
           callback_3();
        }
    }
}

Then each of the callbacks callback_1, callback_2 and callback_3 will always be called on each message regardless of the channel value passed by the server, because channels property is just an array of channels defined in swampdragon.subscribe calls.

@AlexejStukov
Copy link

@aantipov
Ah, now I see your problem. You are subscribing to the same route with 3 different channels. If you want to handle different kinds of messages you have 3 possibilities:

  • Use one channel and filter by the data:
// ...
if (channels[i] == "my_channel") {
    if ("something" in message.data) {
    // your code
    }
}
  • Use get_subscription_contexts(self, **kwags) or get_subscription_channels(self, **kwargs) in the router (depending on what Router-Class you are extending in your backend code, former for ModelRouters and later for BaseRouters) and add subscriptions depending on the information added to the subscription context
swampdragon.subscribe('your_route', "channel_1", {"something":"value_1"}, function (context, data) {
    // subscription success
    }, function (context, data) {
    // subscription fail
});
  • Use different routes for different information.

I would use the first option, if it's the same source sending you different kinds of information, the second approach, if it's the same kind of data, but from different sources and the third if you have different sources. Also you can mix and match that to your liking.

@aantipov
Copy link
Author

@AlexejStukov Thanks for helping.
I do use the first option as a workaround. But I don't like this, because I can see that our server does send the channel value and I can't use it.
Why does swapdragon use channels at all if it prevents onChannelMessage callback from using vital channel info sent by a server?
Why does swampdragon substitute channel info sent by a server for a useless channels list, that I construct by myself?
I can't understand that logic of swampdragon? What were the ideas behind this logic?

@AlexejStukov
Copy link

@aantipov
It enables you to bundle several server_channels to one channel. I think it is intended to use get_subscription_contexts(self, **kwags) or get_subscription_channels(self, **kwargs) or two different routes, depending on your situation.
But I'm not quite sure of that. You might want to ask @jonashagstedt.

@AlexejStukov
Copy link

@aantipov
As an example I use

swampdragon.open(function() {
    {% for object in object_list %}
    swampdragon.subscribe('object-route', "object", {"pk":"{{ object.pk }}"}, function (context, data) {
        }, function (context, data) {
    });
    {% endfor %} {# edit #}
});

in my template and

def get_subscription_contexts(self, **kwargs):
    obj = self.get_object(**kwargs)
    return {"object": kwargs["pk"]}

in my routers.py. With this you can also add authentication (with swampdragon-auth) pretty easy (with an if in both files).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants