0

I am trying to store JavaScript function in the database. Every row in the database will have a different function. Depending on the row called a specific function will execute in the browser.

Some clarification: I am not trying to execute the function at the server. It will only be stored at the server and fetched to the client and would be executed like any other javascript function.

First, my question is, is this possible. I have been reading that javascript allows functions to be stored in variables, so I thought why not in the database. This will give me the freedom to execute a different function based on the row.

Second, I have been getting this error:

>a=cell._cell.row.data.jsfunction
"function toCelsius(fahrenheit) {
  return (5/9) * (fahrenheit-32);
}"
>a()
VM435:1 Uncaught TypeError: a is not a function
    at eval (eval at cellClick (empRead.html:14), <anonymous>:1:1)
    at t.cellClick (empRead.html:21)
    at w.edit (tabulator.min.js:6)
    at HTMLDivElement.<anonymous> (tabulator.min.js:6)

It is a simple Fahrenheit to Celsius conversion function. I am afraid it is treating a variable as a string. But then how to tell it, I want it to be treated as a function. Is there any workaround to achieve it.

thanks

Ivan Kaloyanov
  • 1,748
  • 6
  • 18
  • 24
BB23850
  • 109
  • 1
  • 11
  • 5
    You'd be adding an absolutely massive amount of overhead and complexity if you want to load all your functions from a database - may I ask why you are trying to do this? At some point you'll have to `eval` the string from your database in one way or the other, which is almost always a bad idea. – Scott Jan 07 '19 at 14:18
  • 2
    looks like a string and not a function to me. – epascarello Jan 07 '19 at 14:18
  • Why not simply write a wrapper function with `row` as input that calls the row specific function? – Mortz Jan 07 '19 at 14:20
  • *I am afraid it is treating variable as string* well of course it is, it **is** a string! – Liam Jan 07 '19 at 14:20
  • I tried eval but it is not working. >a=eval(cell._cell.row.data.jsfunction) undefined Also, I want to add, performance is not my concern at the moment. I want to enhance functionality. It is treating function as a string. That is my problem. How to tell it, here it is not string, it is function. – BB23850 Jan 07 '19 at 14:53

3 Answers3

4

A variable is just a means to represent a value.

JavaScript supports lots of different kinds of value, including Numbers, Strings, Arrays and Functions.

To store something in a database, you have to express it as a type of value that the database understands. I'm not aware of any database that supports "JavaScript function" as a data type.

You need, instead, to store some kind of representation of the data in a format that the database does understand.

For example, the source code of the function, which you could then eval on the client (This appears to be what you are attempting, but you forgot the eval part). This opens up a whole can of worms and is not generally recommended.

Typically, the best approach is to have a bunch of predefined functions as part of the client-side JS program (possibly organised as properties of an object) and then store an identifier in the database (e.g. the property name).

You can then so something like:

my_trusted_functions[cell._cell.row.data.jsfunction]();
Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • I tried eval but it is giving error. VM644:1 Uncaught TypeError: eval[cell._cell.row.data.jsfunction] is not a function – BB23850 Jan 07 '19 at 15:04
  • at the same time when I am assigning a function to a variable in JavaScript code, it is working well. – BB23850 Jan 07 '19 at 15:05
  • `eval` is a nasty can of worms. Do not use `eval`. `eval` is a **function**. Functions are called with `()` not `[]`. – Quentin Jan 07 '19 at 15:06
0

Probably not a good idea. In order to store a function correctly you need to store its entire declaration context which is obviously not desirable (if possible). What you could do, as suggested in other answers is creating a DSL for your app and store into the DB a representation of an expression in this DSL, hopefully a lot simpler than a JS AST.

For instance if the domain of your app is working with temperature data you could have some generic functions like convert(from, to, value), add(value1, value2) wich are easily composable. Storing a representation of the convert function is just storing a map of matching between the different units, add is just a composition of convert with the addition.

My advice would be to check if:

  • your domain can be modeled with pure data, if it is the case then bingo, store this and compose it in JS.
  • your domain can be modeled with a DSL, see its complexity and maybe store some kind of representation of it if needed

and act accordingly.

adz5A
  • 2,012
  • 9
  • 10
  • I think I got your idea. I am able to store function name in database and execute it in browser. It should server the purpose to some extent. – BB23850 Jan 07 '19 at 17:14
  • in any case imo the important thing to keep in mind is that in databases are for storing data not procedures. what this means is that in the design phase you should be able to list every type of data may need to use, which ones need to persist and the persistence mechanism. all procedures will live in the applicative part of your app and make use of these types and their representation. it is very important to make a clear distinction between those two concepts. – adz5A Jan 07 '19 at 17:27
  • This is not transactional data. It will be mostly configuration data. – BB23850 Jan 08 '19 at 03:23
0

Yes it is done. Help came from this post:

Given a string describing a Javascript function, convert it to a Javascript function

I used user984003 answer. Thanks a lot user984003.

Here is the solution:

>s = window.document.createElement("script");
>s.innerHTML = cell._cell.row.data.jsfunction
"function toCelsius() {
  return (5/9) * (200-32);
}"
>window.document.body.appendChild(s)
<script>​function toCelsius() {
  return (5/9) * (200-32);
}​</script>​
>toCelsius()
93.33333333333334

Thanks to everybody

BB23850
  • 109
  • 1
  • 11