Home > database >  How elegantly try-catch functoion execution within an array [closed]
How elegantly try-catch functoion execution within an array [closed]

Time:10-06

I have this array:

const arr = [
      { 'Some text': this.f('a') },
      { 'Some other text': this.f('b') }
]

I wrote experimenting with a code to achieve that

arr.forEach((entry) => {
  console.log(Object.entries(entry));
})

As a result it executed my functions:

[[ 'Some text': 'result_f1' ]]
[[ 'Some other text': 'result_f2' ]]

My functions gets executed automatically.

However I do not think that it is the most safest way to achieve that, I want to be more explicit executing each function separate as well as try-catching each function.

The reason I want to do that is to to wrap each function in to separate try-catch block as try-catching within an array is breaking the code readability

Any ideas how to achieve that?

CodePudding user response:

The functions are not being executed "automatically," they're being executed because you're explicitly calling them:

const arr = [
    { 'Some text': this.f('a') },
    //             ^^^^^^^^^^^−−−−−−−−−−−−−− here
    { 'Some other text': this.f('b') }
    //                   ^^^^^^^^^^^−−−−−−−− and here
]

The result of the a bove is an array with two objects in it, where the first object has a property called Some text whose value is the result of having called this.f('a') and the second object has a property called Some other text whose value is the result of having called this.f('b').

If you wanted to delay those calls until some later time, you'd need to wrap them in functions:

const arr = [
    { 'Some text': () => this.f('a') },
    //             ^^^^^^^^^^^^^^^^^−−−−−−−−−−−−−− wrapper function
    { 'Some other text': () => this.f('b') }
    //                   ^^^^^^^^^^^^^^^^^−−−−−−−− wrapper function
]

Later, you'd call them like this:

arr[0]["Some text"]();
arr[0]["Some other tex"]();

or similar.

If you want to call them later wrapped in try/catch blocks, you could do it like this:

for (const obj of arr) {
    for (const fn of Object.values(obj)) {
        try {
            fn();
        } catch (e) {
            // ...
        }
    }
}

...or the equivalent with forEach:

arr.forEach(obj => {
    Object.values(obj).forEach(fn => {
        try {
            fn();
        } catch (e) {
            // ...
        }
    });
});

In another comment you've said:

how would you replace the function with function result?

I suspect you want something like this:

const arr = [
    { 'Some text': () => this.f('a') },
    { 'Some other text': () => this.f('b') }
].map(obj => {
    return Object.fromEntries(Object.entries(obj).map(([key, value]) => {
        try {
            value = value();
        } catch (e) {
            // ...presumably do something with the fact it failed...
        }
        return [key, value];
    }));
});

The result of the above is that arr has objects with the same keys as the initial object literal, but with the values being the result of calling the functions (or whatever you write to value in the catch block).

See:

CodePudding user response:

The function this.f was already called when you defined the array arr. This is what the round braces do. To postpone the invocation you could "bind" the parameters to the function without actually calling the function this.f.bin(this, 'a') instead of this.f('a'). This creates a sort of closure that can be called at a later stage.

In the forEach you could then explicitly call the functions:

arr.forEach((entry) => {
  Object.entries(entry).forEach(([key, fun]) => {
    console.log(key, fun())
  })
})

That being said, I am unsure why one would want to do this.

  • Related