amark / gun

An open source cybersecurity protocol for syncing decentralized graph data.
https://gun.eco/docs
Other
17.96k stars 1.16k forks source link

Unable to remove listener created by .map() function #1314

Open jasoncht1023 opened 1 year ago

jasoncht1023 commented 1 year ago

I have been trying to develop a message function between users with GUN. The messages are stored in gunDB and displayed on the page when a peer account is selected. Here is what I'm trying to do:

<html>
<body>
    <select name="recipients" id="recipients" onchange="displayMessage()">
         <option value="alice">Alice</option>
         <option value="bob">Bob</option>
    </select>

    <p id="chatbox"></p>
<script>
    async function displayMessage() {
        let peer = document.getElementById("recipients").value;
        let messageList = "";
        await gun.get('chat').get(peer).map().once(async (data, key) => {            
            messageList += data + "<br>"
        });   
        document.getElementById("chatbox").innerHTML = messageList;
    }
</script>
</body>
</html>

For example, when the user selects Alice in the select box, the messages between the user and Alice will be displayed. Any subsequent message updates will also be shown as the data in the node is subscribed by the gun.get('chat').get(peer).map().once(cb) function. However, when the user switches to Bob and then back to Alice, gun.get('chat').get(peer).map().once(cb) (where peer is Alice) is called twice in total and the listener for message updates is created twice. Therefore, when there are new messages sent, the messages will be shown twice instead of only once.

Is there a feature to stop .map() function to subscribe to data updates in a node? I've tried to create a variable prevPeer to store the previous peer and call gun.get('chat').get(prevPeer).off() at the beginning of displayMessage() but nothing has changed.

amark commented 1 year ago

chain.off() should remove all listeners at that chain & underneath, rather aggressively. .on(data, key, msg, event){ event.off() should remove that one individual listener. It seems like neither of these are working? I wonder if it is because .map() creates a type of special sub-chain that is not accessible to chain.off() tho it should be... someone willing to debug against https://github.com/amark/gun/blob/master/gun.js#L1290-L1295 ?

pwFoo commented 1 year ago

Is it related to the map callback bug https://github.com/amark/gun/issues/1315? Maybe fix it / rewrite map() would be the solution?