javascriptchaining

Grouping functions together in javascript


I'm trying to group functions together in javascript, though I have some difficulty understanding how to keep track of the groups. In the below example, my question is: How does: "some.get('anotherContent')" knows that it's queried under alias "anotherSomeSome" and not "anotherSome" - What I mean is, how to keep the track of the different aliases in this model? Below is what I have tried, but I find it quiet complex and hard to keep track of the aliases:

class someClass {
    alias(callback) {
        callback();
        return this;
    }

    get(content) {
        return 'some' + content;
    }
}

const some = new someClass();

some.alias('some', () => {
    some.alias('anotherSome', () => {
        some.get('content')
    })
    
    some.get('contents')

    some.alias('anotherSomeSome', () {
        some.get('anotherContent')
    })
})

Solution

  • On the surface it looks like an XY problem... Anyway.

    A simple approach would be argument drilling, thus you pass your alias down the stack with arguments.

    If your code sync you could save your alias in a class property. In my case I save it in path array so the whole stack would be traceable.

    class someClass {
        path = [];
        alias(alias, callback) {
            this.path.push(alias);
            callback();
            this.path.pop();
            return this;
        }
    
        get(content) {
            console.log(this.path.join(' / '), 'some' + content);
        }
    }
    
    const some = new someClass();
    
    some.alias('some', () => {
        some.alias('anotherSome', () => {
            some.get('content')
        })
        
        some.get('contents')
    
        some.alias('anotherSomeSome', () => {
            some.get('anotherContent')
        })
    })

    As soon as you introduce async (and probably more complex) code you need to track your calls. I find it interesting to use a proxy that returns some instance with individual path:

    class someClass {
        path = [];
        alias(alias, callback) {
            callback(new Proxy(this, {
              get(self, prop){
                if(prop === 'path'){
                  return [...self.path, alias];
                }
                return Reflect.get(...arguments);
              }
            }));
            return this;
        }
    
        get(content) {
            console.log(this.path.join(' / '), 'some' + content);
        }
    }
    
    const some = new someClass();
    
    some.alias('some', some => {
        some.alias('anotherSome', some => {
            some.get('content')
        })
        
        some.get('contents')
    
        some.alias('anotherSomeSome', some => {
            some.get('anotherContent')
        })
    })