Sincronizare date JavaScript, front-end si back-end, persistente si in timp real.

Efectuati o modificare in browser si aceasta este trimisa automat la server, salvata in baza de date si partajata cu alti utilizatori. Jinaga are noduri izolate jurnalizate care se apropie de acordul global.

Vedeti un exemplu de aplicatie: ImprovingU – Site de vot pentru idei de curs.

Obtineti o scurta prezentare video a Jinaga.

  • Mutabilitate
  • Securitate
  • Sincronizare
  • Comparatie cu alternative
  • Protocol
  • Foaie de parcurs

Contribuind

Back-end universal

Instalati pachetul Jinaga NPM.

Creati un server.js.

var JinagaDistributor = require (“jinaga / jinaga.distributor.server”); var MongoProvider = require (“jinaga / jinaga.mongo”); var url = ‘mongodb: // localhost: 27017 / dev’; var port = 8888; var mongo = new MongoProvider (url); JinagaDistributor.listen (mongo, mongo, port);

Porniti Mongo.

Rulati aplicatia.

Capatul dvs. din spate ruleaza acum. Petreceti restul timpului pe partea frontala.

In fata

Aplicatia dvs. front-end salveaza fapte ori de cate ori utilizatorul face ceva. Aceste fapte sunt persistente pana la capatul dvs. si sunt impartasite in timp real cu alte browsere.

Instalati biblioteca din partea clientului.

Includeti scriptul in pagina dvs.

<script src = “bower_components / jinaga / jinaga.js”> </script> <script src = “main.js”> </script>

Creati fapte in main.js.

var j = new Jinaga (); j.sync (nou JinagaDistributor (“ws: // localhost: 8888 /”)); j.fact ({type: “Task”, lista: {type: “TodoList”, nume: “Chores”}, descriere: “Scoateti cosul de gunoi”});

Acest cod reprezinta de fapt doua fapte.

porno comic español videos putas maduras
ver sexo gratis coños de viejas
tetudas españolas porno madres peludas
incesto real madre hijo porno traducido español
abuelas follando como folla mi mujer
incesto jovencitas hentaihd
sexso madura cabalgando
penes de abuelos paja en el coche
vidio pirno videosgays
corridas dentro de la boca caras llenas de semen
sobando tetas folladas extremas
sexo camara oculta españa porno casero real español
porno guey orgia bisexual
madura española con joven tetudas españolas
pollas corriendose porno torrent magnet
videos de peliculas eroticas videos de chicas gratis
orgias abuelas parejas pilladas en la calle
peliculas porno de incesto maduras por dinero
glory hole españa www rubias
milfs españolas follando tetudas jovenes

Primul este:

var chores = {type: “TodoList”, name: “Chores”};

Al doilea este:

var trash = {type: “Task”, list: chores, description: “Scoateti cosul de gunoi”};

Al doilea fapt stie despre primul. Aceasta face din primul fapt ( treburi ) un predecesor al celui de-al doilea ( gunoi ). Ordinea dintre aceste doua este cunoscuta. Treburile vor veni intotdeauna inainte de gunoi . Dar faptele fara o astfel de relatie pot aparea in orice ordine.

Priveste

Acum ca puteti exprima ca treburile sunt un predecesor al gunoiului , va recomandam sa urmariti toate faptele cu acelasi predecesor. Acestea se numesc succesori. De exemplu, s-ar putea sa doriti sa gasiti toate sarcinile din lista de treburi . Furnizati un sablon care sa se potriveasca tuturor faptelor dorite. De exemplu, pentru o lista data, acest sablon se va potrivi cu toate sarcinile din lista respectiva:

function tasksInList (l) {return {type: “Task”, list: l}; }

Cand se gaseste un fapt care corespunde sablonului, vrem sa apelam o functie. Vom urmari sablonul si vom apela o functie atunci cand rezultatele se schimba.

functie taskAdded (task) {// Rendereaza sarcina in interfata de utilizare} j.watch (treburi, [tasksInList], taskAdded);

Acum, daca adaug o noua sarcina in lista, va fi apelata functia taskAdded .

var vase = {tip: “Sarcina”, ​​lista: treburi, descriere: “Goliti masina de spalat vase”}; j.fact (vase); // taskAdded se numeste cu preparatul.

Un apel invers este executat o singura data pe fapt. Daca se intampla sa adaugati acelasi fapt din nou, apelul invers nu va fi invocat.

Ceasul este in vigoare pentru sesiunea curenta. Este distrus implicit cu instanta Jinaga cand nu mai este utilizat. Daca doriti sa opriti in mod explicit vizionarea, capturati valoarea returnata.

var watch = j.watch (treburi, [tasksInList], taskAdded); // Ceva timp mai tarziu … watch.stop ();

Conditii

Acum vreau sa marchez o sarcina finalizata. Sa surprindem acest lucru ca pe un alt fapt.

j.fact ({tip: “TaskCompleted”, sarcina: cos de gunoi, finalizat: adevarat});

Sa scriem un sablon care se potriveste acestui fapt pentru o sarcina data.

functie taskIsNotCompleted (t) {return j.not ({type: “TaskCompleted”, task: t, complete: true}); }

Acum putem scrie o interogare, astfel incat numai sarcinile neterminate sa se potriveasca cu sablonul.

function uncompletedTasksInList (l) {return j.where ({type: “Task”, list: l}, [taskIsNotCompleted]); } j.watch (treburi, [uncompletedTasksInList], taskAdded);

Cand se creeaza aceasta interogare, numai activitatile existente care nu au fost finalizate vor fi adaugate la interfata de utilizare. Deci veti vedea „Goliti masina de spalat vase”, dar nu „Scoateti cosul de gunoi”. Dar ce se intampla atunci cand o sarcina se schimba? Vrem sa eliminam sarcinile din interfata de utilizare dupa ce sunt marcate ca fiind finalizate. Deci, hai sa adaugam un alt apel invers la interogare.

function taskRemoved (t) {// Scoateti taskul din interfata de utilizare} j.watch (treburile, [uncompletedTasksInList], taskAdded, taskRemoved);

Acum, cand finalizati o sarcina, functia taskRemoved va fi apelata pentru ao elimina din interfata de utilizare.

j.fact ({tip: “TaskCompleted”, sarcina: feluri de mancare, finalizat: adevarat}); // taskRemoved este apelat cu felul de mancare.

Faptele sunt imuabile, deci nu exista apel invers pentru actualizarea unui rezultat. Acestea pot fi adaugate sau eliminate numai. Pentru a gestiona actualizarile, va rugam sa consultati Mutablity.