My situation is roughly this: I need to create a 'chat flow', into which users can also add self-encapsulated submodules that have their own unique, private channels to communicate on. In other words, users are chatting in chat, user #1 hits an 'add module' button, a uuid is generated and published in a 'newModule' message to the PubNub chat channel, all listeners on that channel receive the message with the uuid, and proceed to create a local copy of the module, which itself subscribes to PubNub channel 'uuid'. Module appears in chat flow, users can continue chatting, but also send (let us say) 'clicks' back and forth from the linked private modules on their own 'uuid' PubNub channels.
Unfortunately, when the new module attempt to subscribe to the new channel, PubNub 'refires' the last event received on the chat channel, triggering creation of a second, duplicate module.
I've created a stripped down test case demonstrating the problem behavior here: http://codepen.io/teolitto/pen/09f75b8b60f69a1c3aaab85af01b3cd3?editors=1000
DOM and Tag definitions:
<AppMain></AppMain>
<script type="riot/tag">
<AppMain>
<h3>AppMain</h3>
<button onclick={ publishNewColorBox }>
New ColorBox
</button>
//logic
var context = this;
context.eventBus = appCore.eventBus;
context.publishNewColorBox = function() {
console.log('1. "New ColorBox" button click handler')
PN.publish({
channel: appCore.channel,
message: {
type: "newColorBox",
boxId: PN.uuid()
}
})
}
context.addNewColorBox = function(boxId){
var cb = document.createElement('ColorBox');
context.root.appendChild(cb);
riot.mount(cb, {boxId: boxId});
}
context.init = function(){
context.eventBus.on('addNewColorBox', function(boxId){
console.log('3. riot "addNewColorBox" event received by application, mounting new ColorBox');
context.addNewColorBox(boxId);
})
}
context.on('mount', function(){
context.init();
})
</AppMain>
<ColorBox>
<div></div>
//logic
var context = this;
context.eventBus = riot.observable();
context.boxId = opts.boxId;
context.init=function(){
console.log('4. ColorBox successfully mounted, subscribing PN to channel ',context.boxId);
PN.subscribe({
//channel: 'someChannel',
channel: context.boxId,
message: function(m){
console.log('box channel received message:',m);
}
});
}
context.on('mount', function(){
context.init();
})
</ColorBox>
</script>
Javascript:
$(function(){
appCore = {
channel: "firstChannel",
eventBus: riot.observable()
}
PN = PUBNUB.init({
publish_key: 'pub-c-92c890df-0f01-4f9b-9084-ec118f452dc9',
subscribe_key: 'sub-c-e8889318-c702-11e5-837e-02ee2ddab7fe'
});
PN.subscribe({
channel: appCore.channel,
message: function(m){
switch(m.type) {
case "newColorBox":
console.log('2. PN channel', appCore.channel, ' received "newColorBox" message. Firing riot event "addNewColorBox"')
appCore.eventBus.trigger('addNewColorBox', m.boxId);
break;
}
}
});
riot.mount('AppMain');
});
I do have muxing ('stream controller') turned on in the PubNub console, so that's not it.
I've found hacks that help ameliorate the problem - setting a timeout of about 33ms before subscribing to the new channel seems to resolve the issue. If the channel being subscribed to is one that's been visited recently, the problem does not occur. However, since I need a new, unique channel every time, and I'd really really prefer to avoid a hacky solution like a timeout (god knows what else I'll run into if I have to do that), I'm asking here. Any ideas? Could this be a bug in PubNub? Or is my implementation shot?
Any input much appreciated.