Werken met gegevens in Sails.js

Sails.js is een nieuw Node.js-framework, met een focus op vrijheid en slimme standaardinstellingen. In dit artikel zullen we enkele van de datafuncties bekijken die Sails out-of-the-box biedt, om eenvoudig complexe apps te maken.


Waarom zeilen anders is dan andere kaders

De reden om voor Sails te kiezen, is het beste van de maker van Sail, Mike McNeil, "Sails is ontstaan ​​uit noodzaak". Veel frameworks die je ziet, zijn bijna gebouwd voor de academische kant van dingen, deze frameworks bevorderen meestal best practices en creëren een platform voor ontwikkelaars om dingen sneller of beter te maken.

Zeilen aan de andere kant, is gemaakt voor productie, het probeert niet om je een nieuwe syntaxis of platform te geven, het is een solide basis, bedoeld voor het creëren van 'client-work' met snelheid. Het contrast kan subtiel zijn, maar er zijn een paar duidelijke verschillen.

Om te illustreren waar ik het over heb, laten we eens kijken naar Meteor. Meteor is waarschijnlijk het toonaangevende JS-platform van vandaag, maar het is een goed voorbeeld van een raamwerk, in het belang van een raamwerk. Nu is dit geen slechte zaak, ik ben een groot voorstander van Meteor, wat ik bedoel is, ze wilden een raamwerk bouwen en ze hebben er goed werk van gemaakt, Mike aan de andere kant wilde het werk van de klant sneller doen . Zeilen is slechts een middel om een ​​einde te maken.

In Meteor wordt vrijwel alles geabstraheerd en je gebruikt JavaScript plus de Meteor API om alles te coderen. Terwijl Sails niet bedoeld is als een nieuw platform, dus niets is verborgen.

Het rust op de top van Socket.io en het populaire Express-framework, en je hebt ze volledig in eigen beheer. Begin je het verschil te zien??

Omdat Sails eerst is afgestemd op productie, is het bovendien uitgerust met meerdere opties voor schaalvergroting en beveiliging.

Er is veel om over te praten, maar in dit artikel zou ik willen focussen op hoe Sails omgaat met data, en hoe je gebruik kunt maken van enkele van de meer geavanceerde functies van Sails om echt coole acties uit te voeren.


Installatie

Voor het geval je nog geen Sails hebt geinstalleerd, kun je dit doen via NPM door te draaien:

sudo npm install -g sails

Socket.io & Express

Laten we nu een beetje praten over Socket.io en Express voordat we Sail ingaan. Er is een goede premium-serie over Express van Andrew Burgess als je geïnteresseerd bent, maar ik zal hier de relevante basisprincipes van beide bibliotheken doornemen:

Socket.io

Socket.io is een pub / subbibliotheek die zowel op de server als op de client wordt uitgevoerd en waarmee ze via web-sockets kunnen spreken.

Een kort voorbeeld kan er ongeveer zo uit zien:

// Code voor server var io = vereisen ("socket.io"); io.sockets.on ("verbinding", functie (sok) sock.emit ("welcomeMessage", hallo: "world"); io.listen (80);

Deze code begint met het vereisen van de socket.io bibliotheek, luisterend naar een verbinding, en dan wanneer een andere contactdoos verbindt, zal het het een bericht verzenden, geadresseerd aan Welkoms bericht evenement en uiteindelijk een aantal JSON doorgeven.

Vervolgens zou je op de client iets schrijven als:

// Code voor client var sock = io.connect ('http: // localhost'); sock.on ('welcomeMessage', functie (json) // Ontvangst van gebeurtenis ontvangen);

Hier maken we verbinding met de server en luisteren we daarnaar Welkoms bericht evenement dat we net hebben gemaakt. Zoals je ziet is het een vrij eenvoudige publish / subscribe-server, die bidirectioneel is (de client kan ook berichten voor de server uitsturen).

Laten we nu eens kijken naar Express:

uitdrukken

De eenvoudigste vorm van een Express-route kan ongeveer zoiets zijn als:

app.get ('/ users', function (req, res) res.send ("Hello from '/ users'!"););

Dit definieert een eenvoudige route, zodat wanneer een gebruiker naar het adres van uw site gaat en toegang probeert te krijgen tot de / gebruikers pagina, krijgen ze het bericht te zien "Hallo van '/ gebruikers'!".

Express is dus een framework voor het afhandelen van HTTP-aanvragen en Socket.io is een websocketcommunicatiebibliotheek. Wat het Sails-team wel heeft gedaan, brengt alle Express-routes intern naar Socket.io. Wat dit betekent is dat je alle HTTP-routes via web-sockets kunt bellen.

Dat is best cool! Maar er ontbreekt nog een stukje van de puzzel en dat zijn de Sails Blueprints.

Met Sails kunt u modellen genereren net als in andere frameworks, het verschil is dat Sails ook een RESTfull-API kan genereren die geschikt is voor productie. Dit betekent dat als u een model genereert met de naam 'gebruikers'je kunt direct RESTfull query's uitvoeren op de'/ gebruikers'bron zonder codering nodig.

Als u nog niet bekend bent met RESTful API's, is dit slechts een manier om toegang te krijgen tot gegevens, waar CRUD-bewerkingen worden toegewezen aan verschillende HTTP-methoden.

Dus a KRIJGEN verzoek om '/ gebruikers'krijgt alle gebruikers, een POST aanvraag maakt een nieuwe gebruiker aan, enz.

Dus wat betekent dit allemaal?

Dit betekent dat we een volledige RESTfull-API hebben die via Sails is toegewezen aan Socket.io, zonder een regel code te schrijven!

Maar waarom zijn sockets beter in het ophalen van gegevens dan in een verzoek van Ajax? Nou, naast een slanker protocol blijven sockets open voor bidirectionele communicatie en heeft Sails hiervan gebruik gemaakt. Sails geeft u niet alleen de gegevens door, maar u wordt automatisch geabonneerd op updates in die database en wanneer iets wordt toegevoegd, verwijderd of bijgewerkt, ontvangt uw klant een melding via de webcontactdoos, zodat u hiervan op de hoogte bent.

Dit is de reden waarom Sails zo geweldig is!


Zeilen + Backbone

Het volgende onderwerp dat ik graag wil bespreken, is de Backbone-integratie, want als je geen JavaScript-framework gebruikt, doe je het verkeerd.

Met dit in gedachten zijn Sails en Backbone het perfecte paar. Backbone, zoals Sails, is buitengewoon onopvallend, alle functies zijn beschikbaar, kunnen worden opgeheven en optioneel.

Als u Backbone eerder hebt gebruikt, weet u misschien dat het native verbinding maakt met REST API's, dus als u out-of-the-box bent, kunt u de gegevens aan de voorkant met uw Sails-applicatie synchroniseren.

Maar genoeg gepraat voor nu, laten we dit allemaal in actie bekijken door een eenvoudige chattoepassing te maken. Om te beginnen, open een terminalvenster en typ:

zeilen nieuwe ChatApp cd ChatApp zeilen genereren modelgebruikers zeilen genereren modelberichten zeilen genereren controllerberichten zeilen genereren controller main

Hiermee wordt een nieuwe app gemaakt en worden enkele bestanden voor ons gegenereerd. U kunt van bovenaf zien dat er twee verschillende bronnen zijn die u kunt genereren; modellen en controllers. Als u bekend bent met het MVC-ontwerppatroon, moet u weten wat deze zijn, maar kortom, modellen zijn dat uw gegevens en controllers uw logica-code bevatten. Dus we hebben twee collecties nodig, één om de gebruikers te houden en één voor de berichten.

Vervolgens hebben we voor de controllers een nodig om de paginaroutes te verwerken, ik noemde het 'hoofd', dan hebben we een tweede controller genaamd'berichten'. Nu vraag je je misschien af ​​waarom ik een controller heb gemaakt met dezelfde naam als de onze berichten model? Nou, als je je dat herinnert, zei ik dat Sails een REST-API voor je kan maken. Wat er gebeurt, is dat Sails, door een lege controller te maken met dezelfde naam als een model, weet terug te vallen en een REST-API voor de bijbehorende resource te bouwen.

Dus, we hebben een controller voor onze gemaakt berichten model, maar het is niet nodig om er een te maken voor het gebruikersmodel, dus ik heb het gewoon weggelaten. En dat is alles wat er is om modellen en controllers te maken.

Laten we vervolgens een aantal routes instellen.

routes

Routes zijn altijd een veilige plek om te beginnen, omdat je meestal een goed idee hebt van welke pagina's gemaakt zullen worden.

Dus open de routes.js bestand dat zich in de config map, kan het in het begin wat overweldigend lijken, maar als u alle opmerkingen verwijdert en de in de volgende routes toevoegt, blijft er ongeveer zoiets over als dit:

module.exports.routes = '/': controller: 'main', action: 'index', '/ signup': controller: 'main', action: 'signup', '/ login':  controller: 'main', actie: 'login', '/ chat': controller: 'main', actie: 'chat';

We hebben een startpagina, een chatpagina en vervolgens twee pagina's voor zowel de aanmeldings- als de aanmeldingspagina's. Ik heb ze allemaal in dezelfde controller geplaatst, maar in Sails kun je zoveel controllers maken als je maar wilt.

modellen

Laten we vervolgens de gegenereerde bekijken berichten model dat zich bij "api> modellen> Messages.js"We moeten de nodige kolommen toevoegen aan ons model. Nu is dit niet absoluut noodzakelijk, maar het zal enkele hulpfuncties voor ons creëren die we kunnen gebruiken:

// Messages Model module.exports = attributes: userId: 'INT', gebruikersnaam: 'STRING', bericht: 'STRING';

Voor de berichten model, we beginnen met de ID kaart van de gebruiker waartoe dit bericht behoort, een gebruikersnaam dus we zullen dit niet apart hoeven te ondervragen, en dan de feitelijke bericht.

Laten we nu het gebruikersmodel invullen:

// Gebruikersmodel module.exports = attributen: gebruikersnaam: 'STRING', wachtwoord: 'STRING';

En dat is alles, we hebben alleen de gebruikersnaam en wachtwoord attributen. De volgende stap is om onze routefuncties te maken binnen de MainController.

Controllers

Dus open de MainController, welke te vinden is bij "api> controllers> MainController.jsLaten we beginnen met het maken van een functie voor elk van de routes die we hierboven hebben gedefinieerd:

var MainController = index: function (req, res) , signup: function (req, res) , login: functie (req, res) , chat: function (req, res) ; module.exports = MainController;

Als u bekend bent met Express, zult u blij zijn om te zien dat deze functies standaard Express routefuncties zijn. Ze ontvangen twee variabelen, req voor het HTTP-verzoek en res om het antwoord te creëren.

Volgens het MVC-patroon biedt Sails een functie voor het weergeven van weergaven. De startpagina heeft niets speciaals nodig, dus laten we gewoon de weergave renderen.

index: functie (req, res) res.view (); ,

Sails leunt meer naar conventie dan naar configuratie, dus wanneer u belt res.view (); Sails zoekt naar een weergavebestand (met een .EJS uitbreiding standaard) met behulp van het volgende patroon: 'weergaven> controllerName> methodName.ejs'. Dus voor deze oproep zoekt het naar 'weergaven> hoofd> index.ejs'. Het is ook vermeldenswaard, deze weergaven bevatten alleen de specifieke delen van de pagina. Als je kijkt naar 'weergaven> layout.ejs', je ziet een oproep in het midden voor <%- body %>, dit is waar uw weergavebestand wordt ingevoegd. Standaard gebruikt dit 'layout.ejs'bestand, maar u kunt andere lay-outbestanden gebruiken door alleen de lay-outnaam in de res.view () functie, onder de eigenschap met de naam 'layout'. Bijvoorbeeld: 'res.view (layout: "other.ejs");'.

Ik ga het standaard lay-outbestand gebruiken met een kleine aanpassing, ik ga jQuery, Backbone en Underscore toevoegen. Dus in de 'layout.ejs'bestand vlak voor de sluiting tag, voeg de volgende regels toe:

  

Als dat klaar is, zijn we nu klaar om de startpagina te maken.

De startpagina

Laten we een nieuwe map maken in de keer bekeken map met de naam hoofd, en binnenkant van ons nieuwe hoofd map, maken we een nieuw bestand met de naam 'index.ejs'.

In het bestand kunnen we een aanmeldings- en aanmeldingsformulier maken:

Code Chat

Log in

Inschrijven

Vrij simpel, alleen de essentie.

De aanmeldings- en inschrijfgebieden

Vervolgens moeten we een kleine JS toevoegen om deze te laten communiceren met de server. Dit is niet specifiek voor Sails, we sturen gewoon een AJAX-verzoek via jQuery naar de Sails-server.

Deze code kan op de pagina zelf worden opgenomen of via een apart JS-bestand worden ingeladen. Voor het gemak zet ik het onderaan dezelfde pagina:

Dit is allemaal standaard JS en jQuery, we luisteren naar de klikgebeurtenis op de inlogknop, zorgen ervoor dat de velden gebruikersnaam en wachtwoord zijn ingevuld en de gegevens in de '/Log in'route. Als de login succesvol is, sturen we de gebruiker door naar de chatpagina, anders wordt de door de server geretourneerde fout weergegeven.

Laten we vervolgens hetzelfde maken voor het aanmeldingsgebied:

$ ("# signupbutton"). klik (functie () var gebruikersnaam = $ ("# signupName"). val (); var wachtwoord = $ ("# signupPassword"). val (); var confirmPassword = $ (" #signupConfirmPassword "). val (); if (gebruikersnaam && wachtwoord) if (wachtwoord === confirmPassword) $ .post ('/ signup', gebruikersnaam: gebruikersnaam, wachtwoord: wachtwoord, ​​functie () window. location = "/ chat";) .fail (functie (res) alert ("Fout:" + res.getResponseHeader ("error"));); else alert ("Wachtwoorden komen niet overeen") ; else alert ("Een gebruikersnaam en wachtwoord is vereist"););

Deze code is zo goed als identiek, dat je waarschijnlijk het hele Ajax-gedeelte in zijn eigen functie kunt abstraheren, maar voor deze tutorial is het prima.

Nu moeten we teruggaan naar onze 'MainControlleren behandel deze twee routes, maar voordat we dat doen, wil ik een knooppuntmodule installeren. We moeten het wachtwoord hashen, zoals platte tekst wachtwoorden zijn niet een goede zaak, zelfs niet voor demonstratie! Ik vond een mooie module genaamd 'wachtwoord-hash' van David Wood die goed zal werken.

Om het te installeren, gaat u vanuit uw terminal naar de hoofdmap van uw Sails-app en typt u: npm installeer wachtwoord-hash.

Zodra dat is geïnstalleerd, laten we het openen MainController en implementeer de twee benodigde routes. Laten we beginnen met inschrijven:

signup: function (req, res) var gebruikersnaam = req.param ("gebruikersnaam"); var wachtwoord = req.param ("wachtwoord"); Users.findByUsername (gebruikersnaam) .done (functie (err, usr) if (err) res.send (500, fout: "DB Error"); else if (usr) res.send (400, error: "Username already Taken"); else var hasher = require ("password-hash"); password = hasher.generate (password); Users.create (username: username, password: password). done (function (error, user) if (error) res.send (500, error: "DB Error"); else req.session.user = user; res.send (user); );); 

Het is een beetje uitgebreid, maar het enige wat we hier doen, is het lezen van de gebruikersnaam en het wachtwoord van de POST-aanvraag en ervoor zorgen dat de gebruikersnaam niet al is gebruikt. Je kunt zien dat ik ook de wachtwoord-rooster gebruik die we zojuist hebben geïnstalleerd, het is super eenvoudig te gebruiken, geef het wachtwoord gewoon door in de genereermethode en het zal het hashen met een willekeurig zout.

Het is ook vermeldenswaard dat op elke mogelijke locatie waar we een fout of probleem tegenkomen, we een HTTP-foutcode terugsturen en een bericht terugsturen via een aangepaste koptekst met de naam 'fout'die, als je het je herinnert, worden weergegeven in een waarschuwingsbericht op de indexpagina.

Een ander opmerkelijk punt, is het feit dat we een 'magische' functie gebruiken genaamd 'findByUsername', dit is mogelijk gemaakt omdat we een gebruikersnaam kolom in ons gebruikersmodel.

Tot slot, onderaan kunt u zien of alles goed is gegaan, we bewaren de gebruiker in een sessievariabele en retourneren deze met een standaardstatuscode van 200, waarmee jQuery weet dat het AJAX-verzoek succesvol was.

Laten we vervolgens de login-functie schrijven:

login: functie (req, res) var gebruikersnaam = req.param ("gebruikersnaam"); var wachtwoord = req.param ("wachtwoord"); Users.findByUsername (gebruikersnaam) .done (functie (err, usr) if (err) res.send (500, fout: "DB Error"); else if (usr) var hasher = require ( "wachtwoord-hash"); if (hasher.verify (wachtwoord, usr.password)) req.session.user = usr; res.send (usr); else res.send (400, error: "Wrong Wachtwoord "); else res.send (404, error:" User not Found ");); 

Nogmaals, dit is erg vergelijkbaar met het vorige inschrijven functie, we zoeken naar een gebruiker met dezelfde gebruikersnaam die op het formulier is gepost en als deze een gebruikersnaam vindt, controleren we of het wachtwoord overeenkomt met het gebruik van de hasher's verifiëren methode. De reden dat we het wachtwoord niet gewoon opnieuw kunnen hashen en doorgeven aan de modellen vind De functie is omdat de hasher een willekeurig zout gebruikt, dus als we het wachtwoord opnieuw hashen zouden het gelijk zijn aan iets anders.

De rest van de code is hetzelfde; als alles uitcheckt, slaan we de gebruiker op in een sessie en retourneren we, anders sturen we een foutmelding terug.

Het inlogsysteem is nu voltooid en we zijn eindelijk in staat om verder te gaan met het bouwen van de chatfunctie.

De chatfunctie bouwen

Omdat we Backbone gebruiken voor het ontvangen van de berichten, zal de daadwerkelijke routefunctie heel eenvoudig zijn. Dit is de complete chatfunctie:

chat: function (req, res) if (req.session.user) res.view (username: req.session.user.username);  else res.redirect ('/'); 

We beginnen door te controleren of de gebruiker ingelogd is of niet, als dit uitcheckt, laadt het de view, geeft het de gebruikersnaam door die in de sessie was, anders gaan we gewoon door naar de startpagina.

Laten we nu een nieuwe weergave maken met de naam 'chat.ejs'binnenkant van de hoofd map. Open het en laten we een eenvoudig formulier maken om nieuwe berichten te plaatsen en een div container voor het weergeven van alle.

Welkom <%= username %>

Dus voor deze weergave hebben we alleen wat standaard HTML gebruikt. Het enige dat enige uitleg behoeft, is het <%= username %> code, deze stijl van coderen is niet specifiek voor Sails, het is eigenlijk de syntaxis voor EJS. Deze syntaxis lijkt veel op de korte tags van PHP. <% is het equivalent van in PHP en <%= is hetzelfde als . Met het eerste fragment van EJS kunt u standaard JS-code op de pagina integreren, terwijl de tweede de code erin afdrukt. Hier drukken we gewoon de gebruikersnaam uit die we hebben doorgegeven van de controller.

De rest van onze chatfunctie is allemaal JavaScript. Laten we, om aan de slag te gaan, eens kijken hoe u de chatfunctionaliteit zou schrijven met de standaard Backbone, en dan zullen we zien hoe u kunt profiteren van web-sockets.

Voeg onderaan de pagina de volgende JS toe:

Omdat Sails automatisch een API maakt die Backbone standaard begrijpt, hoeft er geen extra servercode te worden geschreven, het wordt niet veel eenvoudiger dan dat. Dit is waar ik het over had toen ik zei dat Sails niet gemaakt was om een ​​'raamwerk' te zijn. Het probeert niet om je eigen syntaxis te gebruiken, het is gemaakt om dingen voor elkaar te krijgen en zoals je kunt zien, het levert.

Om het uit te testen, opent u een terminalvenster en navigeert u naar uw Sails-appmap en typt u 'zeilen stijgenom het op te starten. Standaard wordt het gestart naar http: // localhost: 1337. Meld u nu aan en post een paar berichten.

Om uw geplaatste berichten te bekijken, kunt u console.log de berichtenvariabele, of bekijk deze in de console van de browser. Nu is het volgende dat we moeten implementeren een weergave zodat we de geplaatste berichten in de browser kunnen zien.

_.templateSettings = interpolate: /\\(.+?)\\/g; var MessagesView = Backbone.View.extend (el: '#messagesContainer', initialize: function () this.collection.on ('add', this.render, this); this.render ();, sjabloon: _.sjabloon("

message

"), render: function () this. $ el.html (" "); this.collection.each (function (msg) this. $ el.append (this.template (msg.toJSON ())); , this)); var mView = new MessagesView (collection: messages);

We beginnen met het definiëren van een weergave en koppelen deze aan de div die we eerder hebben gemaakt. Vervolgens voegen we een gebeurtenishandler toe aan de verzameling om de div opnieuw te renderen telkens wanneer een nieuw model aan de verzameling wordt toegevoegd.

U ziet bovenaan dat ik de standaard Underscore-instellingen moest veranderen in de EJS-syntaxis binnen de sjablonen, om in plaats daarvan de syntaxis van Moustache te gebruiken. Dit komt omdat de pagina al een EJS-document is, dus het zou op de server worden verwerkt en niet in Underscore.

Notitie: Ik heb hiervoor de Regex niet bedacht, die eer gaat naar de Underscore-documenten zelf.

Ten slotte kunt u onderaan zien dat we een nieuw exemplaar van deze weergave hebben gemaakt door deze de verzamelingsvariabele door te geven.

Als alles goed is gegaan, zou u nu uw berichten in de browser moeten zien en deze zou moeten worden bijgewerkt wanneer u een nieuw bericht maakt.


Zeilt beleid

Nu is het je misschien opgevallen dat we niet de gebruikersnaam of de gebruikersnaam wanneer we de berichten indienen, en dit is voor veiligheidsdoeleinden.

U wilt dit soort controle niet aan de kant van de klant zetten. Als iedereen een JavaScript-variabele moet wijzigen om het account van een andere gebruiker te beheren, heeft u een groot probleem.

Hoe gaat u hiermee om? Met beleid natuurlijk.

Beleidsregels zijn in feite middleware, die worden uitgevoerd vóór het daadwerkelijke webverzoek, waar u het verzoek kunt stopzetten, wijzigen of zelfs omleiden, waar nodig.

Laten we voor deze app een beleid voor onze berichten maken. Beleidsregels worden toegepast op controllers, zodat ze zelfs op normale pagina's kunnen worden weergegeven, maar voor deze tutorial houden we gewoon een voor onze berichten Model.

Maak een bestand met de naam 'MessagesPolicy.js' in de 'api> beleid'map en voer het volgende in:

module.exports = functie (req, res, next) if (req.session.user) var action = req.param ('action'); if (action == "create") req.body.userId = req.session.user.id; req.body.username = req.session.user.username;  volgende ();  else res.send ("U moet aangemeld zijn", 403); ;

Wat is hier aan de hand? Je ziet dat deze functie lijkt op een normale routefunctie, het verschil is echter de derde parameter, die de volgende middleware in de stapel zal oproepen. Als je het idee van middleware nieuw vindt, kun je het denken als een Russische nestpop. Elke laag krijgt het verzoek, samen met de responsvariabelen en deze kunnen ze naar eigen goeddunken aanpassen. Als ze aan alle vereisten voldoen, kan de laag deze verder doorgeven totdat deze het midden bereikt, wat de routefunctie is.

Dus hier zijn we, controleren of de gebruiker is ingelogd, als de gebruiker dat niet is, geven we een 403-fout weer en het verzoek eindigt hier. Anders bellen we (dat wil zeggen, de gebruiker is ingelogd) next (); om het door te geven. In het midden van de bovenstaande code, is waar we enkele postvariabelen injecteren. We passen dit toe op alle oproepen op de 'berichten'-controller (eigenlijk de API), dus we krijgen de actie en controleren of deze aanvraag een nieuw bericht probeert te maken, in welk geval we de berichtvelden voor de gebruiker toevoegen ID kaart en gebruikersnaam.

Open vervolgens de policies.js bestand dat zich in de map config bevindt en voeg het beleid toe dat we zojuist hebben gemaakt. Dus je bestand zou er als volgt uit moeten zien:

module.exports.policies = '*': true, 'messages': 'MessagesPolicy';

Als dit is geplaatst, moeten we alle oude records verwijderen omdat deze deze nieuwe informatie niet bevatten. Sluit dus de Sails-server (ctrl-c) en in hetzelfde terminalvenstertype: rm -r .tmp om de tijdelijke database te verwijderen die ons een schone lei geeft.

Laten we vervolgens de gebruikersnaam toevoegen aan de eigenlijke berichten, dus verander de sjabloon in 'chat.ejs' naar:

sjabloon: _.template ("

username: message

"),

Start de Sails-server opnieuw op (opnieuw met zeilen stijgen) en registreer een andere nieuwe gebruiker om het uit te testen. Als alles goed werkt, zou u in staat moeten zijn om berichten toe te voegen en uw naam in het bericht te zien.

Op dit punt hebben we een vrij goede setup, we halen de post automatisch op met behulp van Backbone en de API, plus we hebben wat basisbeveiliging op zijn plaats. Het probleem is dat het niet wordt bijgewerkt wanneer andere mensen berichten plaatsen. Nu kunt u dit oplossen door een JavaScript-interval en poll voor updates te maken, maar we kunnen het beter doen.

Gebruikmaken van Websockets

Ik noemde eerder dat Sails gebruik maakt van de bidirectionele mogelijkheden van websockets om updates op de geabonneerde gegevens te plaatsen. Met behulp van deze updates kunnen we luisteren naar nieuwe toevoegingen aan de berichtentabel en de verzameling dienovereenkomstig bijwerken.

Dus in de chat.ejs bestand, laten we een nieuw soort verzameling maken; een SailsCollection:

var SailsCollection = Backbone.Collection.extend (sailsCollection: "", socket: null, sync: function (methode, model, opties) var where = ; if (options.where) where = where: options. where if (typeof this.sailsCollection === "string" && this.sailsCollection! == "") this.socket = io.connect (); this.socket.on ("connect", _.bind ( function () this.socket.request ("/" + this.sailsCollection, waarbij, _.bind (function (users) this.set (users);, this)); this.socket.on ("message ", _.bind (function (msg) var m = msg.uri.split (" / "). pop (); if (m ===" create ") this.add (msg.data); else if (m === "update") this.get (msg.data.id) .set (msg.data); else if (m === "destroy") this.remove (this.get (msg.data.id));, this));, this)); else console.log ("Fout: Kan modellen niet ophalen omdat property 'sailsCollection' niet is ingesteld in de verzameling"); );

Nu kan het lang zijn, maar het is eigenlijk heel simpel, laten we er doorheen lopen. We beginnen met het toevoegen van twee nieuwe eigenschappen aan het collectie-object, een om de naam van het Sails-model te behouden en een om de web-socket vast te houden. Vervolgens wijzigen we de synchroniseren functie, als u bekend bent met Backbone, dan weet u dat dit de functie is die een interface vormt met de server wanneer u dingen belt zoals halen. Meestal worden aanvragen van Ajax afgevuurd, maar we gaan het aanpassen voor socketcommunicatie.

Nu gebruiken we niet de meeste functionaliteit die de synchroniseren functie-aanbiedingen, vooral omdat we de mogelijkheid voor gebruikers niet hebben toegevoegd om berichten bij te werken of te verwijderen, maar om volledig te zijn, zal ik ze opnemen in de functiedefinitie.

Laten we eens kijken naar het eerste deel van de synchroniseren functie:

var where = ; if (options.where) where = where: options.where

Deze code controleert eerst of er 'waar'clausules zijn doorgestuurd, hierdoor kunt u dingen doen als: messages.fetch (where: id: 4); om alleen rijen op te halen waar de id gelijk is aan vier.

Daarna hebben we een code die ervoor zorgt dat de 'sailsCollection'eigenschap is ingesteld, anders loggen we een foutmelding. Daarna maken we een nieuwe socket en verbinden we met de server, luisterend naar de verbinding met de op ( 'connect') evenement.

Eenmaal verbonden, vragen we de index van de 'sailsCollection'opgegeven om in de huidige lijst met modellen te komen. Wanneer we de gegevens ontvangen, gebruiken we de collectie's reeks functie om de modellen in eerste instantie in te stellen.

Oke, tot nu toe hebben we het equivalent van de standaard halen commando. Het volgende blok code is waar de pushmeldingen gebeuren:

this.socket.on ("message", _.bind (function (msg) var m = msg.uri.split ("/"). pop (); if (m === "create") this. add (msg.data); else if (m === "update") this.get (msg.data.id) .set (msg.data); else if (m === "destroy") this.remove (this.get (msg.data.id));, this));

De actie die wordt uitgevoerd (of we nu een bericht maken, bijwerken of vernietigen) bevindt zich in het werkelijke msg, wat dan binnen in de uri. Om de actie te krijgen, splitsen we de URI op 'forward slashes' ('/') en pakken we alleen het laatste segment met de knal functie. We proberen het vervolgens aan te passen aan de drie mogelijke acties van creëren, bijwerken, of vernietigen.

De rest is standaard Backbone, we kunnen het gespecificeerde model toevoegen, bewerken of verwijderen. Met onze nieuwe klasse bijna voltooid, hoeft u alleen maar de stroom te veranderen MessageCollection. In plaats van de Backbone-collectie uit te breiden, moet het onze nieuwe collectie uitbreiden, zoals:

var MessageCollection = SailsCollection.extend (sailsCollection: 'messages', model: MessageModel);

Naast het uitbreiden van onze nieuwe collectie, zullen we nog een wijziging aanbrengen, zodat we in plaats van de eigenschap URL instellen, de eigenschap sailsCollection instellen. En dat is alles wat er is. Open de toepassing in twee verschillende