O incercare de apropiere de tehnologia Phoenix.LiveView folosind Python si JavaScript.
Solutia este un modul (extensie de server) pentru serverul meu de aplicatii web, AppServer, si se numeste livedemo.
Acum implementeaza 4 functii executate in server si accesibile din JavaScript din browserul de web: pub, call, init si get:
// ws function to call server
function wsSendVars(ob) {
ws.send(JSON.stringify({ type: "pub", data: ob }));
}
function wsCall(name, args) {
ws.send(JSON.stringify({ type: "call", data: name, args: args }));
}
function wsInit(name, value) {
ws.send(JSON.stringify({ type: "init", data: name, value: value }));
}
function wsGet(name) {
ws.send(JSON.stringify({ type: "get", data: name }));
}
Se pot executa comenzi (call) in server si rezultatul se poate trimite la toti clientii conectati (pub).
Imediat dupa incarcarea paginii de web variabilele folosite in popularea paginii pot fi initializate (init) daca nu au o valoare de pornire, apoi pot fi aduse in memoria browserului si afisate in diferite locuri in pagina web (get).
Demonstratia consta in modificarea unui contor si implementarea unui chat.
Tagurile folosite in html sunt << @variabila >>, << ?variabila valoare_intiala >> si << !nume_functie un_singur_argument >>.
In urma preprocesarii, tagurile definite intre << si >> sunt izolate, transformate si inserate in codul html ca taguri <span></span> cu id unic si apeluri JavaScript.
Sunt ceva probleme cu sesiunea http (Beaker Cache and Session Library) pe partea de websocket, dar cu putina atentie, securitatea nu este compromisa.
Pe partea de server implementarea celor 4 functii:
while True:
data = wsclient.receive()
if data is None:
# client disconnected
break
# expect json data to be a python dict
msg = json.loads(data)
msg_type = msg.get('type')
data = msg.get('data')
if msg_type == "get":
self.broadcast({data: self.vars.get(data)})
if msg_type == "init":
value = msg.get('value')
if not self.vars.get(data):
with self.lock:
self.vars[data] = value
if msg_type == "pub":
with self.lock:
for k, v in data.items():
self.vars[k] = v
self.broadcast(data)
if msg_type == "call":
args = msg.get("args")
func = self.funcs.get(wsclient, {}).get(data)
if func:
func(args)
# client disconnected
with self.lock:
self.clients.remove(wsclient)
try:
del self.funcs[wsclient]
except:
pass