• Главная
  • Карта сайта
Не найдено

Створення програми для опитувань в реальному часі з використанням Node.js, Express, AngularJS і MongoDB

  1. Що вам буде потрібно для створення свого застосування
  2. Запуск програми Express
  3. Малюнок 1. Первісне додаток Express
  4. Лістинг 1. Файл routes / index.js
  5. Лістинг 2. Файл views / index.jade
  6. Малюнок 2. Шаблон додатки для опитувань
  7. Крок 2. Розширення можливостей користувача фронтенда за допомогою AngularJS
  8. Лістинг 3. Елементи скрипта для завантаження середовища Angular і модуля Angular Resource
  9. Створення Angular-модуля
  10. Лістинг 4. Файл public / javascripts / app.js
  11. Лістинг 5. Файл public / javascript / controllers.js
  12. Лістинг 6. Файл public / partials / list.html
  13. Лістинг 7. Файл public / partials / item.html
  14. Лістинг 8. Файл public / partials / new.html
  15. Лістинг 9. Файл public / stylesheets / style.css
  16. Крок 3. Зберігання даних в MongoDB за допомогою Mongoose
  17. Лістинг 10. Додавання рядків в розділі dependencies
  18. Створення Mongoose-моделі
  19. Лістинг 11. Файл models / Poll.js
  20. Лістинг 12. Створення кінцевих точок JSON
  21. Лістинг 13. Файл routes / index.js
  22. Лістинг 14. Файл public / javascripts / services.js
  23. Лістинг 15. Файл public / javascripts / controller.js
  24. Лістинг 16. Файл public / javascripts / controller.js (продовження)
  25. Лістинг 17. Файл public / javascripts / controller.js (продовження)
  26. Малюнок 3. Подивитися варіанти відповіді на питання
  27. Крок 4. Голосування в реальному часі за допомогою Socket.io
  28. Лістинг 18. Файл app.js
  29. Лістинг 19. Файл routes / index.js
  30. Додавання Angular-сервісу для відправки даних в WebSockets
  31. Лістинг 20. Файл public / javascripts / services.js
  32. Лістинг 21. Файл public / javascripts / controllers.js
  33. Малюнок 4. Перегляд результатів опитування
  34. Висновок
  35. Ресурси для скачування

Нещодавно при читанні курсу лекцій з HTML5 для великої групи студентів я захотів провести серед них опитування, а результати їх голосування відображати з оновленням в режимі реального часу. З цією метою я вирішив швидко створити додаток для опитувань. Я хотів обмежитися простою архітектурою і не дуже великою кількістю різних мов і середовищ. З цієї причини я вирішив використовувати JavaScript буквально всюди - Node.js і Express для серверної сторони, MongoDB для бази даних і AngularJS для фронтального призначеного для користувача інтерфейсу.

запустити програму Отримати програмний код

Для управління вихідним кодом свого проекту я вирішив використовувати сервіси DevOps (колишня назва - JazzHub). Це забезпечило мені не тільки повну систему управління версіями для мого коду, але і онлайнову IDE-середовище для редагування мого програмного коду в хмарі і великий набір гнучких засобів управління проектами. Крім того, сервіси DevOps легко інтегруються із середовищем Eclipse, яка має в своєму розпорядженні плагінами для розгортання одним натисканням миші на таких платформах, як Bluemix або Cloud Foundry .

Що вам буде потрібно для створення свого застосування

Крок 1. Побудова базового бекенд-додатки Express

У середовищі Eclipse переключіться на перспективу Node і створіть новий проект Node Express. Якщо ви, як це зробив я, створюєте проект за допомогою DevOps, надайте своїм проектом Node Express таке ж ім'я. Залиште обраним прапорець Jade в розділі template engine (механізм шаблонів). Середа Eclipse автоматично завантажить npm-модулі, необхідні для створення простого додатка Express.

Запуск програми Express

У браузері Project Explorer знайдіть файл app.js в кореневому каталозі свого проекту, натисніть на нього правою кнопкою і виберіть Run As> Node Application. В результаті цього запуститься веб-сервер, після чого на ньому буде розгорнуто цю програму. Після цього відкрийте свій браузер і перейдіть за адресою http: // localhost 3000 .

Малюнок 1. Первісне додаток Express

Конфігурація базового фронтенда

Додаток для опитувань використовує середу Bootstrap як призначеного для користувача інтерфейсу і розмітки загального призначення. Тепер ми внесемо в додаток Express певні зміни для відображення цієї обставини. Спочатку відкрийте файл routes / index.js і змініть властивість title, присвоївши йому значення Polls:

Лістинг 1. Файл routes / index.js
exports.index = function (req, res) {res.render ( 'index', {title: 'Polls'}); };

Потім змініть шаблон views / index.jade з метою включення Bootstrap. Jade - це лаконічний мову шаблонів, компільований в HTML. У ньому використовується структурування тексту відступами з метою усунення необхідності в закривають тегах, що значно зменшує розмір шаблонів. Ми будемо використовувати Jade тільки для розмітки основної сторінки. На наступному кроці ми будемо використовувати часткові Angular-шаблони, щоб додати необхідну функціональність до цієї сторінки.

Лістинг 2. Файл views / index.jade
doctype 5 html (lang = 'en') head meta (charset = 'utf-8') meta (name = 'viewport', content = 'width = device-width, initial-scale = 1, user-scalable = no' ) title = title link (rel = 'stylesheet', href = '// netdna.bootstrapcdn.com/bootstrap/3.0.1/ css / bootstrap.min.css') link (rel = 'stylesheet', href = '/ stylesheets / style.css ') body nav.navbar.navbar-inverse.navbar-fixed-top (role =' navigation ') div.navbar-header a.navbar-brand (href =' # / polls ') = title div .container div

Щоб побачити зміни в своєму додатку, ми "уб'ємо" процес веб-сервера в середовищі Eclipse і знову запустимо файл app.js.

Малюнок 2. Шаблон додатки для опитувань

Примітка. При використанні шаблонів Jade не забувайте належним чином структурувати свій код за допомогою відступів, оскільки в іншому випадку ви зіткнетеся з проблемами. Крім того, не змішуйте різні стилі відступів, оскільки в цьому випадку Jade видасть помилки.

Крок 2. Розширення можливостей користувача фронтенда за допомогою AngularJS

Щоб приступити до використання середовища Angular, спочатку вам потрібно включити її і додати кілька директив у свою HTML-сторінку. У шаблоні views / index.jade змініть елемент html наступним чином:
html (lang = 'en', ng-app = 'polls').

Усередині head-блоку цього файлу додайте наступні елементи скрипта. :

Лістинг 3. Елементи скрипта для завантаження середовища Angular і модуля Angular Resource
script (src = '// ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js') script (src = '// ajax.googleapis.com/ajax/libs/angularjs/1.0 .8 /angular-resource.min.js ')

Потім змініть елемент body в шаблоні, додавши атрибут ng-controller (щоб згодом зв'язати користувальницький інтерфейс з кодом керуючої логіки контролера):
body (ng-controller = 'PollListCtrl').

І, нарешті, змініть останній елемент div в шаблоні, включивши в нього атрибут ng-view: div (ng-view).

Створення Angular-модуля


Вражаюча особливість Angular - зв'язування даних, що забезпечує автоматичне оновлення уявлень при внесенні змін у внутрішні моделі. Це радикально зменшує обсяг JavaScript-коду, який необхідно написати розробнику, оскільки позбавляє від непростого завдання управління DOM.

За замовчуванням додаток Express публікує статичні ресурси, такі як вихідні файли JavaScript, таблиці стилів CSS і зображення з каталогу public в проекті розробника. В каталозі public створіть новий підкаталог з ім'ям javascripts. У цьому підкаталозі створіть файл з ім'ям app.js. Цей файл буде містити Angular-модуль для додатка, який визначає маршрути і шаблони для застосування в інтерфейсі.

Лістинг 4. Файл public / javascripts / app.js
angular.module ( 'polls', []) .config ([ '$ routeProvider', function ($ routeProvider) {$ routeProvider. when ( '/ polls', {templateUrl: 'partials / list.html', controller: PollListCtrl }). when ( '/ poll /: pollId', {templateUrl: 'partials / item.html', controller: PollItemCtrl}). when ( '/ new', {templateUrl: 'partials / new.html', controller: PollNewCtrl}). otherwise ({redirectTo: '/ polls'});}]);

Angular-контролери визначають контекст додатки, надаючи уявленням дані і методи для зв'язування.

Лістинг 5. Файл public / javascript / controllers.js
// Управління списком опитування function PollListCtrl ($ scope) {$ scope.polls = []; } // Голосування / перегляд результатів опитування function PollItemCtrl ($ scope, $ routeParams) {$ scope.poll = {}; $ Scope.vote = function () {}; } // Створення нового опитування function PollNewCtrl ($ scope) {$ scope.poll = {question: '', choices: [{text: ''}, {text: ''}, {text: ''}]}; $ Scope.addChoice = function () {$ scope.poll.choices.push ({text: ''}); }; $ Scope.createPoll = function () {}; }

Створення часткових HTML-шаблонів

Для представлення даних від контролерів середу Angular використовує часткові HTML-шаблони, які дозволяють задіяти наповнювачі та вирази для включення даних і для виконання таких дій, як умовні оператори і ітератори. В каталозі public створіть новий підкаталог з ім'ям javascripts. Для нашого застосування ми створимо три часткових шаблону. Перший частковий шаблон відобразить список доступних опитувань. Ми скористаємося Angular для спрощення фільтрації цього списку у вмісті пошукового поля.

Лістинг 6. Файл public / partials / list.html
<Div class = "page-header"> <h1> Poll List </ h1> </ div> <div class = "row"> <div class = "col-xs-5"> <a href = "# / new "class =" btn btn-default "> <span class =" glyphicon glyphicon-plus "> </ span> New Poll </a> </ div> <div class =" col-xs-7 "> <input type = "text" class = "form-control" ng-model = "query" placeholder = "Search for a poll"> </ div> </ div> <div class = "row"> <div class = "col -xs-12 "> <hr> </ div> </ div> <div class =" row "ng-switch on =" polls.length "> <ul ng-switch-when =" 0 "> <li> <em> No polls in database. Would you like to <a href="#/new"> create one </a>? </ Li> </ ul> <ul ng-switch-default> <li ng-repeat = "poll in polls | filter: query "> <a href="#/poll/{{poll._id}}"> {{poll.question}} </a> </ li> </ ul> </ div> <p> & nbsp; < / p>

Другий частковий шаблон дозволяє користувачеві переглядати опитування. Він використовує Angular-директиву switch для визначення того, чи проголосував даний користувач. За результатами цієї перевірки шаблон відображає або форму для голосування в опитуванні, або діаграму з результатами опитування.

Лістинг 7. Файл public / partials / item.html
<Div class = "page-header"> <h1> View Poll </ h1> </ div> <div class = "well well-lg"> <strong> Question </ strong> <br> {{poll.question }} </ div> <div ng-hide = "poll.userVoted"> <p class = "lead"> Please select one of the following options. </ p> <form role = "form" ng-submit = " vote () "> <div ng-repeat =" choice in poll.choices "class =" radio "> <label> <input type =" radio "name =" choice "ng-model =" poll.userVote "value = "{{choice._id}}"> {{choice.text}} </ label> </ div> <p> <hr> </ p> <div class = "row"> <div class = "col- xs-6 "> <a href="#/polls" class="btn btn-default" role="button"> <span class =" glyphicon glyphicon-arrow-left "> </ span> Back to Poll </ div> <div class = "col-xs-6"> <button class = "btn btn-primary pull-right" type = "submit"> Vote & raquo; </ button> </ div> </ div> </ form> </ div> <div ng-show = "poll.userVoted"> <table class = "result-table"> <tbody> <tr ng-repeat = "choice in poll.choices"> <td> {{ choice.text}} </ td> <td> <table style = "width: {{choice.votes.length /poll.totalVotes*100}}%;"> <tr> <td> {{choice.votes. length}} </ t d> </ tr> </ table> </ td> </ tr> </ tbody> </ table> <p> <em> {{poll.totalVotes}} votes counted so far. <Span ng-show = "poll.userChoice"> You voted for <strong> {{poll.userChoice.text}} </ strong>. </ Span> </ em> </ p> <p> <hr> </ p> <p> <a href="#/polls" class="btn btn-default" role="button"> <span class = "glyphicon glyphicon-arrow-left"> </ span> Back to Poll List </a> </ p> </ div> <p> & nbsp; </ p>

Третій і останній частковий шаблон визначає форму, яка дозволяє користувачеві створювати нові опитування. Він пропонує користувачеві ввести питання і три варіанти відповіді. У розпорядження користувача надається кнопка, що дозволяє додавати додаткові варіанти. Пізніше ми перевіримо, що користувач ввів не менше двох варіантів - оскільки опитування як такої має на увазі наявність декількох варіантів відповіді.

Лістинг 8. Файл public / partials / new.html
<Div class = "page-header"> <h1> Create New Poll </ h1> </ div> <form role = "form" ng-submit = "createPoll ()"> <div class = "form-group" > <label for = "pollQuestion"> Question </ label> <input type = "text" ng-model = "poll.question" class = "form-control" id = "pollQuestion" placeholder = "Enter poll question"> </ div> <div class = "form-group"> <label> Choices </ label> <div ng-repeat = "choice in poll.choices"> <input type = "text" ng-model = "choice. text "class =" form-control "placeholder =" Enter choice {{$ index + 1}} text "> <br> </ div> </ div> <div class =" row "> <div class =" col -xs-12 "> <button type =" button "class =" btn btn-default "ng-click =" addChoice () "> <span class =" glyphicon glyphicon-plus "> </ span> Add another </ button> </ div> </ div> <p> <hr> </ p> <div class = "row"> <div class = "col-xs-6"> <a href = "# / polls" class = "btn btn-default" role = "button"> <span class = "glyphicon glyphicon-arrow-left"> </ span> Back to Poll List </a> </ div> <div class = "col-xs -6 "> <button class =" btn btn-primary pull-right "type =" submit "> Create Poll & raquo; </ button> </ div> </ div> <p> & nbsp; </ p> </ form>

І, нарешті, для відображення результатів нам потрібно додати кілька CSS-декларацій в файл style.css. Замініть вміст цього файлу наступним кодом.

Лістинг 9. Файл public / stylesheets / style.css
body {padding-top: 50px; } .Result-table {margin: 20px 0; width: 100%; border-collapse: collapse; } .Result-table td {padding: 8px; } .Result-table> tbody> tr> td: first-child {width: 25%; max-width: 300px; text-align: right; } .Result-table td table {background-color: lightblue; text-align: right; }

Якщо запустити додаток в цій точці, ми побачимо порожній список опитувань. При спробі створити нове опитування ви зможете побачити форму і додати додаткові варіанти, але не зможете зберегти опитування. Ми зв'яжемо все воєдино на наступному кроці.

Крок 3. Зберігання даних в MongoDB за допомогою Mongoose

Для зберігання даних наш додаток використовує драйвер MongoDB і npm-модулі Mongoose. Ці засоби дозволяють з додатком взаємодіяти з базою даних MongoDB. Щоб отримати ці модулі, відкрийте файл package.json в кореневому каталозі програми та в розділі dependencies додайте наступні рядки. .

Лістинг 10. Додавання рядків в розділі dependencies
"Mongodb": "> = 1.3.19", "mongoose": "> = 3.8.0",

Збережіть цей файл, натисніть правою кнопкою на його ім'я у вікні Project Explorer і виберіть Run As> npm install. В результаті ваших дій буде встановлено npm-модулі і все додаткові залежності.

Створення Mongoose-моделі

Створіть в кореневому каталозі свого застосування новий підкаталог з ім'ям models і в цьому підкаталозі створіть новий файл з ім'ям Poll.js. У цьому підкаталозі ми визначимо нашу Mongoose-модель, яка буде використовуватися для запиту даних і їх збереження в MongoDB в структурованому вигляді.

Лістинг 11. Файл models / Poll.js
var mongoose = require ( 'mongoose'); var voteSchema = new mongoose.Schema ({ip: 'String'}); var choiceSchema = new mongoose.Schema ({text: String, votes: [voteSchema]}); exports.PollSchema = new mongoose.Schema ({question: {type: String, required: true}, choices: [choiceSchema]});

Завдання API-маршрутів до сховища даних

Потім потрібно вказати кілька маршрутів в файлі app.js в кореневому каталозі свого застосування з метою створення кінцевих точок JSON, які можуть бути використані для запитів до MongoDB і її поновлення з боку Angular-коду на стороні клієнта. Знайдіть рядок app.get ( '/', routes.index) і додайте після неї наступний код.

Лістинг 12. Створення кінцевих точок JSON
app.get ( '/ polls / polls', routes.list); app.get ( '/ polls /: id', routes.poll); app.post ( '/ polls', routes.create);

Тепер нам потрібно реалізувати ці функції. Замініть вміст файлу routes / index.js наступним кодом.

Лістинг 13. Файл routes / index.js
var mongoose = require ( 'mongoose'); var db = mongoose.createConnection ( 'localhost', 'pollsapp'); var PollSchema = require ( '../ models / Poll.js'). PollSchema; var Poll = db.model ( 'polls', PollSchema); exports.index = function (req, res) {res.render ( 'index', {title: 'Polls'}); }; // API-інтерфейс JSON для списку опитувань exports.list = function (req, res) {Poll.find ({}, 'question', function (error, polls) {res.json (polls);}); }; // API-інтерфейс JSON для отримання окремого опитування exports.poll = function (req, res) {var pollId = req.params.id; Poll.findById (pollId, '', {lean: true}, function (err, poll) {if (poll) {var userVoted = false, userChoice, totalVotes = 0; for (c in poll.choices) {var choice = poll.choices [c]; for (v in choice.votes) {var vote = choice.votes [v]; totalVotes ++; if (vote.ip === (req.header ( 'x-forwarded-for') | | req.ip)) {userVoted = true; userChoice = {_id: choice._id, text: choice.text};}}} poll.userVoted = userVoted; poll.userChoice = userChoice; poll.totalVotes = totalVotes; res. json (poll);} else {res.json ({error: true});}}); }; // API-інтерфейс JSON для створення нового опитування exports.create = function (req, res) {var reqBody = req.body, choices = reqBody.choices.filter (function (v) {return v.text! = ''; }), pollObj = {question: reqBody.question, choices: choices}; var poll = new Poll (pollObj); poll.save (function (err, doc) {if (err ||! doc) {throw 'Error';} else {res.json (doc);}}); };

Зв'язування даних з фронтенда за допомогою Angular-сервісів

На даний момент бекенд додатки налаштований таким чином, щоб дозволяти запитувати і зберігати опитування в базі даних, проте ми повинні внести в середу Angular певні зміни, щоб вона знала, як взаємодіяти з бекенд. Це легко зробити за допомогою Angular-сервісів, які обгортають процес взаємодії з серверної стороною в безпосередні виклики функцій

Лістинг 14. Файл public / javascripts / services.js
angular.module ( 'pollServices', [ 'ngResource']). factory ( 'Poll', function ($ resource) {return $ resource ( 'polls /: pollId', {}, {query: {method: 'GET', params: {pollId: 'polls'}, isArray: true} })});

Після створення цього файлу необхідно включити його в шаблон index.jade. Додайте нижче останнього елемента скрипта в розділі head наступний рядок
script (src = '/ javascripts / services.js').

Крім того, ми повинні вказати Angular-додатком використовувати цей сервісний модуль. Для цього відкрийте файл public / javascripts / app.js і змініть перший рядок, щоб вона виглядала наступним чином:
angular.module ( 'polls', [ 'pollServices']).

Нарешті, змініть Angular-контролери так, щоб вони використовували створений сервіс для відправки запитів і для збереження опитувань в базі даних. У файлі public / javascripts / controllers.js змініть функцію PollListCtrl наступним чином ..

Лістинг 15. Файл public / javascripts / controller.js
function PollListCtrl ($ scope, Poll) {$ scope.polls = Poll.query (); } ...

Оновлення функцію PollItemCtrl, щоб вона отримувала опитування за його ідентифікатором (ID).

Лістинг 16. Файл public / javascripts / controller.js (продовження)
... function PollItemCtrl ($ scope, $ routeParams, Poll) {$ scope.poll = Poll.get ({pollId: $ routeParams.pollId}); $ Scope.vote = function () {}; } ...

Аналогічним чином змініть функцію PollNewCtrl, щоб вона відправляла нові дані опитування на сервер при поданні форми.

Лістинг 17. Файл public / javascripts / controller.js (продовження)
... function PollNewCtrl ($ scope, $ location, Poll) {$ scope.poll = {question: '', choices: [{text: ''}, {text: ''}, {text: ''}] }; $ Scope.addChoice = function () {$ scope.poll.choices.push ({text: ''}); }; $ Scope.createPoll = function () {var poll = $ scope.poll; if (poll.question.length> 0) {var choiceCount = 0; for (var i = 0, ln = poll.choices.length; i <ln; i ++) {var choice = poll.choices [i]; if (choice.text.length> 0) {choiceCount ++}} if (choiceCount> 1) {var newPoll = new Poll (poll); newPoll. $ save (function (p, resp) {if (! p.error) {$ location.path ( 'polls');} else {alert ( 'Could not create poll');}}); } Else {alert ( 'You must enter at least two choices'); }} Else {alert ( 'You must enter a question'); }}; }

виконання програми

Ви майже досягли кінцевої мети! У цій точці наш додаток має дозволяти користувачам переглядати і шукати опитування, створювати нові опитування і переглядати варіанти голосування по кожному з опитуванням. Перед запуском програми переконайтеся в наявності у вас бази даних MongoDB, що виконується локально. Зазвичай для цього достатньо відкрити термінал або командний рядок і виконати команду mongod. Чи не закривайте вікно терміналу в процесі виконання свого застосування.

Малюнок 3. Подивитися варіанти відповіді на питання

Після запуску програми перейдіть за адресою http: // localhost 3000 в своєму браузері і створіть кілька опитувань. При натисканні мишею на будь-якої опитування ви зможете побачити доступні варіанти відповідей, однак поки не зможете здійснювати реального голосування по цьому опитуванню або побачити його результати. Ми вирішимо це завдання на наступному, заключному, етапі.

Крок 4. Голосування в реальному часі за допомогою Socket.io


Технологія WebSockets дозволяє серверній стороні безпосередньо взаємодіяти з клієнтською стороною і відправляти їй повідомлення.

Єдине, що нам залишилося зробити - сформувати функціональність голосування. Наше додаток дозволить користувачам голосувати, і в міру голосування результати будуть оновлюватися в режимі реального часу на будь-яких підключених клієнтів. Цю функціональність можна легко реалізувати за допомогою npm-модуля socket.io. Щоб зробити це, виконайте наступні кроки.

Відкрийте файл package.json в кореневому каталозі свого застосування і додайте в розділ dependencies наступний рядок:
"Socket.io": "~ 0.9.16".

Збережіть цей файл, натисніть правою кнопкою у вікні Package Explorer і виберіть Run As> npm install, щоб встановити відповідний npm-модуль.

Потім відкрийте файл app.js в кореневому каталозі програми та видаліть блок server.listen ... в самому кінці файлу, замінивши його наступним фрагментом.

Лістинг 18. Файл app.js
... var server = http.createServer (app); var io = require ( 'socket.io'). listen (server); io.sockets.on ( 'connection', routes.vote); server.listen (app.get ( 'port'), function () {console.log ( 'Express server listening on port' + app.get ( 'port'));});

Потім змініть шаблон index.jade, щоб включити клієнтську бібліотеку socket.io. При виконанні нашого застосування ця бібліотека автоматично стане доступною в зазначеному місцезнаходження, тому нам не потрібно піклуватися про самостійне знаходженні цього файлу. Не забудьте включити наступний рядок відразу ж після рядка, в якій ви включили бібліотеку Angular-ресурсу в шаблон:
script (src = '/ socket.io/socket.io.js').

І, нарешті, нам потрібно створити функцію голосування таким чином, щоб нове голосування зберігалося, коли користувач відправляє повідомлення в socket.io, і щоб після цього всім клієнтам надсилалося повідомлення з оновленими результатами. Додайте наступний фрагмент в кінець файлу index.js в каталозі маршрутів.

Лістинг 19. Файл routes / index.js
// API-інтерфейс Socket для збереження голосування exports.vote = function (socket) {socket.on ( 'send: vote', function (data) {var ip = socket.handshake.headers [ 'x-forwarded-for'] || socket.handshake.address.address; Poll.findById (data.poll_id, function (err, poll) {var choice = poll.choices.id (data.choice); choice.votes.push ({ip: ip} ); poll.save (function (err, doc) {var theDoc = {question: doc.question, _id: doc._id, choices: doc.choices, userVoted: false, totalVotes: 0}; for (var i = 0 , ln = doc.choices.length; i <ln; i ++) {var choice = doc.choices [i]; for (var j = 0, jLn = choice.votes.length; j <jLn; j ++) {var vote = choice.votes [j]; theDoc.totalVotes ++; theDoc.ip = ip; if (vote.ip === ip) {theDoc.userVoted = true; theDoc.userChoice = {_id: choice._id, text: choice. text};}}} socket.emit ( 'myvote', theDoc); socket.broadcast.emit ( 'vote', theDoc);});});}); };

Примітка. Не дивуйтеся тому, що додаток шукає заголовок 'x-forwarded-for' до звичайного властивості IP-адреси - це повинно гарантувати використання коректного IP-адреси клієнта в разі розгортання програми в середовищі з вирівнюванням навантаження. Наприклад, це необхідно для належного функціонування програми при розгортанні в середовищі Bluemix або Cloud Foundry.

Додавання Angular-сервісу для відправки даних в WebSockets

Тепер внутрішня функціональність для WebSockets готова. Все, що нам залишилося зробити - прив'язати фронтенд для відправки і пріслушіванія socket-подій. Найкращий підхід до вирішення цього завдання полягає в додаванні нового Angular-сервісу. Замініть вміст файлу services.js в каталозі public / javascripts наступним кодом.

Лістинг 20. Файл public / javascripts / services.js
angular.module ( 'pollServices', [ 'ngResource']). factory ( 'Poll', function ($ resource) {return $ resource ( 'polls /: pollId', {}, {query: {method: 'GET', params: {pollId: 'polls'}, isArray: true} })}). factory ( 'socket', function ($ rootScope) {var socket = io.connect (); return {on: function (eventName, callback) {socket.on (eventName, function () {var args = arguments; $ rootScope. $ apply (function () {callback.apply (socket, args);});});}, emit: function (eventName, data, callback) {socket.emit (eventName, data, function () {var args = arguments; $ rootScope. $ apply (function () {if (callback) {callback.apply (socket, args);}});})}};});

І, нарешті, нам потрібно відредагувати контролер PollItemCtrl таким чином, щоб він прослуховував результати голосування і видавав відповідні повідомлення в WebSockets. Замініть вихідний контролер наступним кодом.

Лістинг 21. Файл public / javascripts / controllers.js
... function PollItemCtrl ($ scope, $ routeParams, socket, Poll) {$ scope.poll = Poll.get ({pollId: $ routeParams.pollId}); socket.on ( 'myvote', function (data) {console.dir (data); if (data._id === $ routeParams.pollId) {$ scope.poll = data;}}); socket.on ( 'vote', function (data) {console.dir (data); if (data._id === $ routeParams.pollId) {$ scope.poll.choices = data.choices; $ scope.poll. totalVotes = data.totalVotes;}}); $ Scope.vote = function () {var pollId = $ scope.poll._id, choiceId = $ scope.poll.userVote; if (choiceId) {var voteObj = {poll_id: pollId, choice: choiceId}; socket.emit ( 'send: vote', voteObj); } Else {alert ( 'You must select an option to vote for'); }}; } ...

Перегляд кінцевого продукту в дії

Додаток для опитувань готове. Переконайтеся, що утиліта mongod все ще виконується, і знову запустіть Node-додаток в середовищі Eclipse. Введіть в браузері адресу http: // localhost 3000 і перейдіть до опитування і голосування. Ви повинні побачити результати. Щоб спостерігати оновлення в реальному часі, знайдіть свій локальний IP-адресу і замініть значення localhost цією адресою. Потім зверніться за цією адресою за допомогою іншої машини в своїй локальній мережі або навіть зі смартфона або планшета. Коли ви будете голосувати за допомогою іншого пристрою, результати будуть автоматично відображатися на цьому пристрої, а також будуть автоматично передаватися в браузер вашого основного комп'ютера.

Малюнок 4. Перегляд результатів опитування

Наступні кроки: подальша доробка і розгортання

Додаток для опитувань, яке ми тільки що створили, є відмінною початковою точкою, проте багато в ньому можна вдосконалити. При плануванні подібних додатків мені подобається застосовувати agile-методику з такими її елементами, як епопеї (epic), призначені для користувача історії (story), розбиття проекту на спринти (sprint) і т. Д. Для цього проекту я використовував сервіси DevOps. Це сильно спростило розробку завдяки розміщенню всіх допоміжних матеріалів проекту і його вихідного коду в одному хмарному репозитарії.

Після того, як вас буде задовольняти якість вашого застосування, наступний крок полягає в його передачі в колективне користування. У минулому розгортання навіть простого додатка могло виявитися справжнім кошмаром, проте до сьогоднішнього дня ситуація змінилася найсприятливішим чином. Сумісна з IBM Cloud Foundry платформа Bluemix дозволяє розгорнути додатки в хмарі всього за кілька хвилин з мінімальним обсягом конфігурації і практично без будь-яких складнощів.

Висновок

Для розробників настав прекрасний час. У нашому розпорядженні є безліч платформ та інструментів, які не тільки спрощують і прискорюють розробку чудових додатків, але і роблять її більш приємним заходом. У цій статті ви навчилися створювати додаток з використанням так званого стека MEAN (Mongo, Express, Angular, Node). Коли-небудь цей стек зможе перевершити стек LAMP (Linux, Apache, MySQL, PHP), який є синонімом простоти в сфері розробки та розгортання веб-додатків. Що стосується мене, я сповнений очікувань.

Оригінал статті: Build a real-time polls application with Node.js, Express, AngularJS, and MongoDB

Ресурси для скачування

Схожі тими

Підпішіть мене на ПОВІДОМЛЕННЯ до коментарів

Would you like to <a href="#/new"> create one </a>?
Провайдеры:
  • 08.09.2015

    Batyevka.NET предоставляет услуги доступа к сети Интернет на территории Соломенского района г. Киева.Наша миссия —... 
    Читать полностью

  • 08.09.2015
    IPNET

    Компания IPNET — это крупнейший оператор и технологический лидер на рынке телекоммуникаций Киева. Мы предоставляем... 
    Читать полностью

  • 08.09.2015
    Boryspil.Net

    Интернет-провайдер «Boryspil.net» начал свою работу в 2008 году и на данный момент является одним из крупнейших поставщиков... 
    Читать полностью

  • 08.09.2015
    4OKNET

    Наша компания работает в сфере телекоммуникационных услуг, а именно — предоставлении доступа в сеть интернет.Уже... 
    Читать полностью

  • 08.09.2015
    Телегруп

    ДП «Телегруп-Украина» – IT-компания с 15-летним опытом работы на рынке телекоммуникационных услуг, а также официальный... 
    Читать полностью

  • 08.09.2015
    Софтлинк

    Высокая скоростьМы являемся участником Украинского центра обмена трафиком (UA — IX) с включением 10 Гбит / сек... 
    Читать полностью