amark / gun

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

Referencing nodes that hold only primitive values #1359

Open gustavcorpas opened 8 months ago

gustavcorpas commented 8 months ago

Edit 02:

Okay. I suppose the problem here is that because a new node is not created when doing: const info = gun.get("foo").get("info").put("fido"); this is essentially the same thing as doing: const info = gun.get("foo").get("info");.

Then when referencing the thing node, .on will only be called if thing actually gets a value.

        const info = gun.get("foo").get("element");
        gun.get("foo").get("pet").put(info); // put a reference to info

        setTimeout(() => {
            info.get("name").put("fido"); // actually make info into a node
        }, 2000);

        console.log(test_name, await gun.get("foo").get("pet")); // will be called after 2 seconds

I have investigated further and it seems that this only works when using gun and not gun.user(). This is not great as user should inherit the gun functions and I would expect them to work the same...

This is a larger code example highlighting the differences:


    const run = async () => {
        localStorage.clear();
        const gun = Gun();
        const user = gun.user();

        user.create("alice", "alicepass", () => {
            user.auth("alice", "alicepass", async (ack) => {

                test(user, "user"); // test the gun user. This will log "user undefined" (does not work)
            })
        })

        test(gun, "gun"); // test on just gun. This will log "gun {_: {…}, name: 'fido'}" (does work)

    }

    async function test(gun, test_name){

        const info = gun.get("foo").get("info");
        gun.get("foo").get("pet").put(info);

        setTimeout(() => {
            info.get("name").put("fido");
        }, 2000);

        console.log(test_name, await gun.get("foo").get("pet"));

    }

Edit 01:

Issue was originally called "Buggy behaviour when awaiting chains" It seems that doing .on will not fire if you put a reference to a node, that contains only a primitive value...?

gun.get("foo").get("name").on(name => console.log("name is: ", name)); // never runs

const thing = gun.get("thing").get("element").put("alice");
gun.get("foo").get("name").put(thing);       

Original Issue

You can await gun chain and get the value residing at them. This lists some examples, illustrating buggy behaviour.

I created these tests in a .html file using the script import of gun.

This works:

            const name = await gun.get("foo").get("name"); // there is nothing here...
            console.log(name); // will log undefined

This works:

            const thing = gun.get("thing").get("element").put({val: "alice"});
            gun.get("foo").get("name").put(thing);

            const name = await gun.get("foo").get("name");
            console.log(name); // will log alice

This does NOT work:

            const thing = gun.get("thing").get("element").put("alice");
            gun.get("foo").get("name").put(thing);

            const name = await gun.get("foo").get("name"); // stalls
            console.log(name); // will never be called
bmatusiak commented 8 months ago

gun is not promise/async based..

the best way to handle async stuff is to wrap with your own promise logic like this example

var Gun = require("gun")
var gun = Gun();

async function getData() {
    return new Promise((res) => {
        var chain = gun.get("test").get("hello").on((data) => {
            if (data) {
                chain.off();
                res(data)
            }
        })
    })
}

async function putData(data) {
    gun.get("test").get("hello").put(data)
    return await getData()
}

async function run() {
    var data = await putData("world");
    console.log(data)
}

run();
gustavcorpas commented 8 months ago

gun is not promise/async based..

the best way to handle async stuff is to wrap with your own promise logic like this example

I believe this is very close to what is implemented already in gun.then and what I think is used to "trick" js into woking with await's - because for the most part awaiting works fine. see docs

I realized however, that the issue is not so much a problem with await but that in general the .on call is not fired!

This does not work:

gun.get("foo").get("name").on(name => console.log("name is: ", name)); // never runs

const thing = gun.get("thing").get("element").put("alice");
gun.get("foo").get("name").put(thing);