Reputation: 754
As you know, there are certain cases (e.g., use in workers) when functions need to be serializable (and, at the other side, deserializable of course). I have such a case; a library function (i.e. I cannot change it) doSomething(serializableFunction)
expects such a function from me. Also it expects that serializableFunction
accepts 1 parameter x
and gives x
to it.
So far, this was not a problem for me; I had one function f(x)
from another library that fulfilled my purposes (so I just called doSomething(f)
so far). But now, I have a second serializable function g(x)
, also from a library, and I want the function I give to doSomething
to execute either f
or g
, dependent on x
. So I tried:
doSomething(function h(x) {
if (x < 5) return f(x);
else return g(x);
});
This would work well without serialization, but with it, an error is thrown of course because h
is not serializable anymore: It calls f
and g
, which are no longer known at deserialization time!
So currently I'm doing:
doSomething(eval(`function h(x) {
const f = ${f.toString()};
const g = ${g.toString()};
if (x < 5) return f(x);
else return g(x);
}`));
This works, but it's a nightmare! So my question is: Is there any better approach to merge 2 serializable functions (like f
and g
) into 1 function that is also serializable? Note that I cannot change any of f
, g
, or doSomething
, just h
!
Upvotes: 0
Views: 64
Reputation: 5927
I think of a solution replacing eval
with new Funciton
.
Not the best, but a bit better.
Example below:
function f(a) {
console.log("f", a);
}
function g(b) {
console.log("f", b);
}
function doSomething(func) {
const y = 1;
func(y);
}
const funcBody = `return function () {
const f = ${f.toString()};
const g = ${g.toString()};
if (x < 5) return f(x);
else return g(x);
}()`;
const func = new Function("x", funcBody);
doSomething(func);
Or you can add some abstraction like below:
function f(a) {
console.log("f", a);
}
function g(b) {
console.log("f", b);
}
function doSomething(func) {
const y = 1;
func(y);
}
const getFuncArray = (name = "x") => [
name,
`return function () {
const f = ${f.toString()};
const g = ${g.toString()};
if (${name} < 5) return f(${name});
else return g(${name});
}()`,
];
const res = new Function(...getFuncArray());
doSomething(res);
Upvotes: 0