0

Not sure how 'smart' of an idea this is but I really wanted to experiement with Vue and Javascript and see if I could condense some code a bit (you could say I've done the opposite).

Anways... I have an data object in vue:

            eventOptions: {
                eventType: {
                    data: [],
                    method: 'getEventTypeList',
                    service: 'ReportEventService',
                },
                eventSeverity: {
                    data: [],
                    service: 'ReportEventService',
                    method: 'getSeverityList',
                },
                eventImpact: {
                    data: [],
                    service: 'ReportEventService',
                    method: 'getBusinessImpactList',
                },
                eventStatus: {
                    data: [],
                    service: 'ReportEventService',
                    method: 'getEventStatusList',
                },
            },

And I want to loop through it in the following method and create a function like:

ReportEventService.getEventStatusList() which is referencing an imported javascript file.

        async setEventOptions() {
            const promises = Object.keys(this.eventOptions).map((key) => {
                const { method, service = this.eventOptions[key]
                return new Promise(async (resolve, reject) => {
                    try {
                        const response = await service[method]();
                        resolve(response);
                    } catch (e) {
                        reject(e);
                    }
                });
            });

            Promise.all(promises)
                .then((responseArray) => {
                    Object.keys(this.eventOptions).forEach((key, index) => {
                        this.eventOptions[key]['data'] =
                            responseArray[index].data;
                    });
                })
                .catch((e) => console.log(e));
        },

Unfortunately, it's not working.

This line fails:

const callback = service[method]();

Any idea how I can convert two strings to make a function that I can execute? I also understand this undertaking is silly and I can probably just list them out and it would be 10x easier.

I did try:

const func = new Function(`${service}.${method}()`)

The error I get is: TypeError: service[method] is not a function

Riza Khan
  • 2,712
  • 4
  • 18
  • 42
  • [“Variable” variables in JavaScript](https://stackoverflow.com/q/5187530) - put your services in an object/map and look them up by the name. – VLAZ Jul 15 '21 at 20:37
  • 1
    Your nearly there, just don't put the service in quotes. eg. `service: ReportEventService` – Keith Jul 15 '21 at 20:42
  • @Keith put that answer down below and I'll mark it as the answer. – Riza Khan Jul 15 '21 at 20:45

2 Answers2

4

Object literals can store Object / classes / functions.. etc.

Your currently just storing a string, 'ReportEventService', so when you call the method your doing 'ReportEventService'[method]() and that doesn't make much sense.

But if you store the Object that is ReportEventService instead, you will be calling.. ReportEventService[method]()

IOW: service: ReportEventService, instead of service: 'ReportEventService',

Keith
  • 22,005
  • 2
  • 27
  • 44
2

If you can use any as part of eventOperations, then there is no reason at all to use strings.

Instead make them into callbacks:

eventType: {
    data: [],
    method: 'getEventTypeList',
    service: 'ReportEventService',
},

can become

eventType: {
    data: [],
    callback: () => ReportEventService.getEventTypeList(),
},

Then you can call it as

const response = await callback();

It you can use a lot more tools to verify your code. At the very least a rename refactoring will work without needing to consider random strings. You can also verify if the method exists or if it is called with the correct number of parameters.

Moreover, you also get more freedom - if you change ReportEventService.getEventTypeList() in the future to require parameters, you can change the callback to () => ReportEventService.getEventTypeList("foo", 42) without having to change the code that consumes it.

VLAZ
  • 26,331
  • 9
  • 49
  • 67
  • This is certainly good advice, especially with refactoring etc. I think the OP was mainly experimenting with his comment. `really wanted to experiement` But having this extra info is very useful, so upvote from me.. – Keith Jul 15 '21 at 21:10
  • This is definitely cleaner then my implementation and I will probably end up using it. Thanks for your answer. – Riza Khan Jul 15 '21 at 21:11