2

Context

while working on a modular architecture, I try to make as much "weak" dependencies as possible. For that purpose I use a "bridgeService" that handle all inter-module interactions.

Problem

I would use the bridgeService as follow:

// in moduleA.js
bridgeService.moduleB.functionA();

But if moduleB does not exists this wil throw an error cannot read property functionA of undefined or bridgeService.moduleB.functionA is not a function.

Expectations

My will is that it fails softly. If any of the properties in the property chain is missing, this will log a warning, return null or false AND prevent all further properties to get called.

Actual code

Here is what I got at the moment:

// Proxy handler
const safeNotInstanciatedWarningProxy = {
    get: function (object, prop) {
        if (prop in object) return object[prop];
        else {
            console.warn(`${prop} not defined`);
            return new Proxy({}, safeNotInstanciatedWarningProxy);
        }
    }
}

const bridgeService = new Proxy({}, safeNotInstanciatedWarningProxy)

This will never throw the first cannot read property functionA of undefined error. But when the last function get called, I can't get rid of the is not a function error.

Is there a way to achieve exactly what I want in javascript ? If not, what would be the best alternative ?

Thanks for your lights

TOPKAT
  • 6,667
  • 2
  • 44
  • 72
  • 3
    Maybe not exactly what you want but if you use Node >=v14 you could give [optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) a try. – NullDev Jul 18 '20 at 11:03
  • Not a bad idea, this will lead to `bridgeService.moduleB?.functionA?();` – TOPKAT Jul 18 '20 at 11:07
  • 1
    Yea, but with `?.` instead of `?` only, between `functionA` and `()`. Otherwise it's probably treated as ternary – NullDev Jul 18 '20 at 11:09
  • 2
    Your `safeNotInstanciatedWarningProxy` is a function that returns a handler object, but you never call that function! Just drop the `() =>`. – Bergi Jul 18 '20 at 14:50

1 Answers1

1

I can't get rid of the is not a function error.

You can make the proxy wrap a function instead:

return new Proxy(() => {
    console.warn("… and is not a function");
}, safeNotInstanciatedWarningProxy);

Of course, this will fail once your modules expects the methods to return something.

Here is an example on codePen

TOPKAT
  • 6,667
  • 2
  • 44
  • 72
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Not a bad idea. However, I will not always know when it's gonna be a function in the property stack. It can be either `a.b.c()` or `a.b.c.d.e()`. The ideal will be this to work in both cases – TOPKAT Jul 20 '20 at 16:53
  • Doesn't matter. They're all functions. `a.b.c` is a function and the proxy gives it a `.d` property. So are `b, `d` and `e` (and possibly even `a` itself). – Bergi Jul 20 '20 at 16:58
  • In fact it works very well! I didn't exactly understand it at first sight. I have added a sample code to be more explicit. – TOPKAT Jul 20 '20 at 17:42