True reactive programming in JavaScript
With no framework, you can program by formulas like with a spreadsheet thank to dynamic features of JavaScript.
Reactive programming is the third level of high-level programming: The first level has been reached with the emergence of languages like Fortran and Basic, and in 1967 Simula has taken us to another level with objects, now implemented in all languages. The time has surely come to reach a new level.
Because RP is closer to the way a man thinks than imperative programming (recipe like), and I'm not talking about functional programming!
An example. If I want to assess how far I can drive along with different car models, I would write:
Then all I have to do is enter the tank capacity and consumption of different car models and I still have its autonomy. No extra line of code is needed, it is just like in a spreadsheet, the first application of RP.
RP is best suited to program a robot, a simulation, or give intelligence to a game. Outputs, such as distance above, can be displayed via an interface or can be commands to a real machine or a virtual object.
There are several frameworks that claim to add reactive programming to JavaScript, but it is not evident from the tests I've done, as they can not recalculate a formula assigned to a variable. They just merely spread events, so it's what is called event programming. The script below allows a program to function like a spreadsheet, all formulas are recalculated when a parameter changes. That's why I added "true" next "reactive programming" in the title.
Having developed a script in PHP after the JavaScript version, I enjoyed to have been able to implement this paradigm so simply in JS, thanks to the dynamism of language.
In JavaScript I implements it in an object that takes 20 lines of code ...
var Reactol = (function() {
Reactol.prototype.add = function(x) {
this.depend.push(x)
}
Reactol.prototype.change = function(x) {
if(x != undefined) this.value = x
for(var i in this.depend) {
var d = this.depend[i]
d.action()
d.change()
d.output()
}
}
function Reactol() {
this.depend=[]
this.value=0
}
return Reactol;
})();
As you can see, I use a closure to add a constructor to the Reactol object.
The table depends lists the objects that depend on the current object. The add method adds a dependency.
When we want to change the value of the object, the change method is called which in turn calls the action, change and output method of each variables, that depends on it.
Declaring a reactive variable
Reactive variable is represented by a Reactol object, so first we declare an instance of the object:
var v1 = new Reactol()
Then we define the formula that must be assigned to this variable:
v1['action'] = function() { this.value = 10 }
We may also add a method to display the contents of the variable. It could also be a command to a device.
v1['output'] = function() { document.getElementById("sum").value = this.value }
Now we create a dependency, we define another variable v2 which depends on the variable v1.
var v2 = new Reactol()
v2['action'] = function() { this.value = v1.value + 1000 }
v1.add(v2)
We must call the add method to add v2 to the list of variables that depend on v1. Thereafter, each change in v1 result in automatic updates to v2.
Nothing more is needed to make our variables reactive!
Example in an HTML page
We have two variables v1 and v2 that are assigned from text fields in an HTML page.
We want to define a new variable sum whose value is the sum of v1 and v2, which will also be displayed in a text field. So every time the user change the value of v1 or v2, sum will be updated automatically.
Here are the JavaScript and HTML code:
var Reactol = (function(){
Reactol.prototype.add = function(x) {
this.depend.push(x)
}
Reactol.prototype.change = function(x) {
if(x != undefined) this.value = x
for(var i in this.depend) {
var d = this.depend[i]
d.action()
d.change()
d.output()
}
}
function Reactol() {
this.depend=[]
this.value=0
}
return Reactol
})();
var v1 = new Reactol()
var v2 = new Reactol()
var sum = new Reactol()
sum["action"] = function() { this.value = parseInt(v1.value) + parseInt(v2.value) }
sum["output"] = function() { document.getElementById("sum").value = this.value }
v1.add(sum)
v2.add(sum)
<p>Value 1 : <input type="text" name="v1" onKeyUp="v1.change(this.value)"> </p>
<p>Value 2 : <input type="text" name="v2" onKeyUp="v2.change(this.value)"> </p>
<p>Sum : <input type="text" name="sum" id="sum"> </p>
This simplistic example is used only to show how the Reactol object works. We could get the same result without the object, of course, but if there were fifty widgets dependent of each other it would be more difficult to manage and in this case, reactive programming comes into its own.
Demonstration
Value 1 :
Value 2 :
Sum :
Download the full source code. The script is under the MIT license. Use it freely but do not display it on a Web page without credit.
Reactive programming is implemented in the Scriptol to JavaScript compiler (written by myself), using the object described here. You have just to state formulas, the compiler takes care of automatically declaring dependencies.
By Denis Sureau, on September 18, 2014.