国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
使用 Node.js、Express、AngularJS 和 MongoDB 構(gòu)建一個實時問卷調(diào)查應(yīng)用程序

最近,在向大學(xué)生們介紹 HTML5 的時候,我想要對他們進(jìn)行問卷調(diào)查,并向他們顯示實時更新的投票結(jié)果。鑒于此目的,我決定快速構(gòu)建一個用于此目的的問卷調(diào)查應(yīng)用程序。我想要一個簡單的架構(gòu),不需要太多不同的語言和框架。因此,我決定對所有一切都使用 JavaScript — 對服務(wù)器端使用 Node.js 和 Express,對數(shù)據(jù)庫使用 MongoDB,對前端用戶界面使用 AngularJS。

這個 MEAN 堆棧(Mongo、Express、Angular 和 Node)只需要一天即可完成,遠(yuǎn)比 Web 應(yīng)用程序開發(fā)和部署所用的 LAMP 堆棧(Linux、Apache、MySQL 和 PHP)簡單得多。

我選擇使用 JazzHub 來管理我的項目的源代碼。它不僅為我的代碼提供了一個完整的版本控制系統(tǒng),還為在云中編輯代碼提供了一個在線 IDE,以及用于項目管理的敏捷特性。JazzHub 很容易與 Eclipse 相集成,Eclipse 還提供了一些插件,支持對平臺( 比如BlueMix或 Cloud Foundry )的一鍵式部署。

構(gòu)建該應(yīng)用程序的先決條件

第 1 步. 構(gòu)建一個基礎(chǔ) Express 后臺

在 Eclipse 中,切換到 Node 透視圖,并創(chuàng)建一個新的 Node Express 項目。如果您創(chuàng)建了一個 JazzHub 項目,請像我所做的那樣,使用相同的名稱為您的 Node Express 項目命名。選擇使用 Jade 作為模板引擎。Eclipse 會自動下載所需的 npm 模塊,以便創(chuàng)建一個簡單 Express 應(yīng)用程序。

運行這個 Express 應(yīng)用程序

在 Project Explorer 中,找到位于您項目的根目錄中的 app.js,右鍵單擊并選擇 Run As > Node Application 。這將啟動一個 Web 服務(wù)器并將應(yīng)用程序部署到該服務(wù)器。 接下來,打開瀏覽器并導(dǎo)航到 http://localhost:3000 。

圖 1. Starter Express 應(yīng)用程序

配置基礎(chǔ)前端

這個問卷調(diào)查應(yīng)用程序?qū)ΤR娪脩艚缑婧筒季质褂昧薆ootstrap 框架?,F(xiàn)在,讓我們對 Express 應(yīng)用程序做一些改動來反映這一點。首先,打開 routes/index.js,將標(biāo)題屬性更改為 Polls :

清單 1. routes/index.js

exports.index = function(req, res){             res.render('index', { title: 'Polls' });         };

接著,更改 views/index.jade 模板以包含 Bootstrap。Jade 是一種速記模板語言,可編譯成 HTML。它使用縮進(jìn)消除了對結(jié)束標(biāo)簽的需求,極大地縮小了模板的大小。您只需要使用 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

想要查看對您的應(yīng)用程序所做的更改,請結(jié)束 Eclipse 中的 Web 服務(wù)器進(jìn)程,再次運行 app.js 文件:

圖 2. 問卷調(diào)查應(yīng)用程序樣板文件

注意:在使用 Jade 模板時,注意適當(dāng)縮進(jìn)您的代碼,否則您會遇到麻煩。另外,還要避免使用混合縮進(jìn)樣式,如果您嘗試這樣做,Jade 將會報錯。

第 2 步. 使用 AngularJS 提供前端用戶體驗

如果要使用 Angular,首先需要在您的 HTML 頁面中包含它,還需要在 HTML 頁面中添加一些指令。在 views/index.jade 模板中,對 html 元素進(jìn)行如下更改: 
html(lang='en', ng-app='polls') 。

在該文件的標(biāo)頭中添加以下腳本元素: :

清單 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) 。

構(gòu)建 Angular 模塊


Angular 中令人影響較為深刻的特性就是數(shù)據(jù)綁定,在后臺模型發(fā)生改變時,該功能會自動更新您的視圖。這極大地減少了需要編寫的 JavaScript 的數(shù)量,因為它對凌亂的 DOM 操作任務(wù)進(jìn)行了抽象。

在默認(rèn)情況下,Express 發(fā)布了靜態(tài)資源,比如 JavaScript 源文件、CSS 樣式表以及位于您項目的公共目錄中的圖像。在公共目錄中,創(chuàng)建一個名為 javascripts 的新的子目錄。在這個子目錄中,創(chuàng)建一個名為 app.js 的文件。該文件將包含用于應(yīng)用程序的 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 控制器定義了應(yīng)用程序的范圍,為要綁定的視圖提供數(shù)據(jù)和方法。

清單 5. public/javascript/controllers.js

// Managing the poll list        function PollListCtrl($scope) {          $scope.polls = [];        }        // Voting / viewing poll results        function PollItemCtrl($scope, $routeParams) {          $scope.poll = {};          $scope.vote = function() {};        }        // Creating a new poll        function PollNewCtrl($scope) {          $scope.poll = {            question: '',            choices: [{ text: '' }, { text: '' }, { text: '' }]          };          $scope.addChoice = function() {            $scope.poll.choices.push({ text: '' });          };          $scope.createPoll = function() {};        }

創(chuàng)建局部 HTML 和模板

為了呈現(xiàn)來自控制器的數(shù)據(jù),Angular 使用了局部 HTML 模板,該模板允許您使用占位符和表達(dá)式來包含數(shù)據(jù)和執(zhí)行操作,比如條件和迭代操作。在公共目錄中,創(chuàng)建一個名為 partials 的新的子目錄。我們將為我們的應(yīng)用程序創(chuàng)建 3 個局部模板,第一個局部模板將會展示可用投票的列表,我們將使用 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> </p>

第二個局部模板允許用戶查看投票。它使用 Angular 切換指令來確定用戶是否已投票,并根據(jù)這些判斷,顯示一個就此次問卷調(diào)查進(jìn)行投票的表格,或者一個包含顯示問卷調(diào)查結(jié)果的圖表。

清單 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"><spanclass="glyphicon glyphicon-arrow-left"></span> Back to Poll              </div>              <div class="col-xs-6">                <button class="btn btn-primary pull-right" type="submit">  Vote ?</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}}</td></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> </p>

第三個也是最后一個局部模板定義了支持用戶創(chuàng)建新的問卷調(diào)查的表單。它要求用戶輸入一個問題和三個選項。提供一個按鈕,以便允許用戶添加額外的選項。稍后,我們將驗證用戶至少輸入了兩個選項 — 因為如果沒有幾個選項,就不能稱之為問卷調(diào)查。

清單 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 ?</button>            </div>          </div>          <p> </p>        </form>

最后,為了顯示結(jié)果,我們需要向 style.css 添加一些 CSS 聲明。將該文件的內(nèi)容替換為以下內(nèi)容:

清單 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;        }

此時,如果您運行該應(yīng)用程序,就會看到一個空的問卷調(diào)查列表。如果您試著創(chuàng)建一個新的問卷調(diào)查,就能看到此表單并添加更多的選項,但您不能保存該問卷調(diào)查。我們將在下一步中詳細(xì)介紹所有這些內(nèi)容。


回頁首

第 3 步. 使用 Mongoose 在 MongoDB 中存儲數(shù)據(jù)

為了存儲數(shù)據(jù),該應(yīng)用程序使用了 MongoDB 驅(qū)動程序和 Mongoose npm 模塊。它們允許應(yīng)用程序與 MongoDB 數(shù)據(jù)庫進(jìn)行通信。要獲得這些模塊,請打該應(yīng)用程序根目錄中的 package.json 文件,并在依賴關(guān)系部分中添加以下這些代碼行:。

清單 10. 向依賴關(guān)系添加下列代碼

"mongodb": ">= 1.3.19",        "mongoose": ">= 3.8.0",

保存文件,在 Project Explorer 中右鍵單擊并選擇 Run As > npm install 。這將安裝 npm 模塊和其他所有依賴關(guān)系。

創(chuàng)建一個 Mongoose 模型

在您應(yīng)用程序的名為 models 的根目錄中創(chuàng)建一個新的子目錄,并在這個子目錄中創(chuàng)建一個名為 Poll.js 的新文件。在這個文件中,我們定義了我們的 Mongoose 模型,該模型將用于查詢數(shù)據(jù),并以結(jié)構(gòu)化數(shù)據(jù)的形式將這些數(shù)據(jù)保存到 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]        });

定義數(shù)據(jù)存儲的 API 路由

接下來,在您應(yīng)用程序的根目錄下的 app.js 文件中設(shè)置一些路由,以便創(chuàng)建一些 JSON 端點,這些端點可用于根據(jù) Angular 客戶端代碼來查詢和更新 MongoDB。找到app.get('/', routes.index) 行,并將下列代碼添加到這一行的后面: :

清單 12. 創(chuàng)建 JSON 端點

app.get('/polls/polls', routes.list);        app.get('/polls/:id', routes.poll);        app.post('/polls', routes.create);

現(xiàn)在,您需要實現(xiàn)這些功能。將 routes/index.js 文件的內(nèi)容替換為下列代碼:

清單 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'});        };        // JSON API for list of polls        exports.list = function(req, res) {           Poll.find({}, 'question', function(error, polls) {            res.json(polls);          });        };        // JSON API for getting a single poll        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});            }          });        };        // JSON API for creating a new poll        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 服務(wù)將數(shù)據(jù)綁定到前端

此時,設(shè)置后臺,以便啟用查詢,并將問卷調(diào)查數(shù)據(jù)保存到數(shù)據(jù)庫,但我們需要在 Angular 中做一些更改,以便讓它知道如何與數(shù)據(jù)庫進(jìn)行通信。使用 Angular 服務(wù)很容易完成這項任務(wù),它將與服務(wù)器端進(jìn)行通信的過程包裝到了簡單的函數(shù)調(diào)用中:

清單 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 }            })          });

在創(chuàng)建的這一文件之后,您需要將它包括在您的 index.jade 模板中。在文件標(biāo)頭部分的最后一個腳本元素的下面添加以下這行代碼: 
script(src='/javascripts/services.js') 。

您還需要告訴您的 Angular 應(yīng)用程序使用這個服務(wù)模塊。要實現(xiàn)這一點,請打開 public/javascripts/app.js 并將第一行更改為可讀,如下所示: 
angular.module('polls', ['pollServices']) 。

最后,更改 Angular 控制器,以便使用該服務(wù)在數(shù)據(jù)庫中進(jìn)行查詢和存儲問卷調(diào)查數(shù)據(jù)。在 public/javascripts/controllers.js 文件中,將 PollListCtrl 更改如下:。

清單 15. public/javascripts/controller.js

function PollListCtrl($scope, Poll) {          $scope.polls = Poll.query();        }   ...

更新 PollItemCtrl 函數(shù),以便根據(jù)問卷調(diào)查的 ID 來查詢某個問卷調(diào)查:

清單 16. public/javascripts/controller.js (continued)

...        function PollItemCtrl($scope, $routeParams, Poll) {          $scope.poll = Poll.get({pollId: $routeParams.pollId});          $scope.vote = function() {};        } ...

類似地,更改 PollNewCtrl 函數(shù),以便在提交表單時將新調(diào)查數(shù)據(jù)發(fā)送到服務(wù)器。

清單 17. public/javascripts/controller.js (continued)

...        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');            }          };        }

運行應(yīng)用程序

您已經(jīng)離成功不遠(yuǎn)了!此時,應(yīng)用程序應(yīng)該允許用戶查看和搜索問卷調(diào)查數(shù)據(jù)、創(chuàng)建新的問卷調(diào)查并查看單個問卷調(diào)查的投票選項。在運行該應(yīng)用程序之前,請確保您已經(jīng)本地運行 MongoDB。這通常和打開一個終端或命令提示符以及運行 mongod 命令一樣簡單。確保在您運行應(yīng)用程序時終端窗口處于打開狀態(tài):

圖 3. 查看一個問卷調(diào)查的選項

在運行應(yīng)用程序之后,在您的瀏覽器中導(dǎo)航到 http://localhost:3000 并創(chuàng)建一些問卷調(diào)查。如果您單擊一個問卷調(diào)查,您就能夠看到可用的選項,但是,您無法實際對該問卷調(diào)查進(jìn)行投票,或者暫時看不到問卷調(diào)查結(jié)果。我們將在下一步和最后一步中對此進(jìn)行介紹。


回頁首

第 4 步. 使用 Socket.io 進(jìn)行實時投票


Web Sockets 允許服務(wù)器端直接與客戶端通信以及向客戶端發(fā)送消息。

剩下的惟一需要構(gòu)建的特性就是投票功能。該應(yīng)用程序允許用戶進(jìn)行投票,在他們投票后,會在所有已連接的客戶端上實時更新投票結(jié)果。使用 socket.io 模塊很容易完成這項工作,現(xiàn)在就讓我們來實現(xiàn)它吧。

打開您應(yīng)用程序的根目錄中的 package.json 文件,將下列代碼添加到依賴關(guān)系部分: 
"socket.io": "~0.9.16" 。

保存文件,在 Package Explorer 中右鍵單擊,然后選擇 Run As > npm install 來安裝 npm 模塊。

接下來,打開應(yīng)用程序根目錄中的 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 客戶端庫。在運行該應(yīng)用程序時,該庫會自動在指定的位置上變得可用,因此不需要擔(dān)心自己如何尋找該文件。確保想包含模板中的 angular-resource 庫的行的后面包含此文件: 
script(src='/socket.io/socket.io.js') 。

最后,您需要創(chuàng)建投票功能,以便在用戶向 socket.io 發(fā)送消息時保存新的投票,并在具有更新結(jié)果時將消息發(fā)送給所有客戶端。將 添加到路由目錄中的 index.js 文件的結(jié)尾處:

清單 19. routes/index.js

// Socket API for saving a vote        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);              });                 });          });        };

注意:如果您想知道為什么應(yīng)用程序會在常規(guī) API 地址屬性的前面查找標(biāo)頭 'x-forwarded-for' ,因為這將確保當(dāng)應(yīng)用程序被部署到負(fù)載平衡環(huán)境中時,所使用的是正確的客戶端 IP。如果您將該應(yīng)用程序部署到 BlueMix 或 Cloud Foundry,這對于應(yīng)用程序是否能正常工作至關(guān)重要。

添加一個 Angular 服務(wù)將數(shù)據(jù)發(fā)送到 Web 套接字。

Web Sockets 的后端功能現(xiàn)已創(chuàng)建完畢。目前剩下要做的工作是綁定前端,以發(fā)送和監(jiān)聽套接字事件。最佳方法是添加一個新的 Angular 服務(wù)。使用以下代碼替換 public/javascripts 文件夾中的 services.js 文件:

清單 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 控制器,以便它能夠監(jiān)聽和發(fā)送用于投票的 Web Socket 消息。將原始控制器替換為:

清單 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');            }          };        }   ...

查看最終產(chǎn)品

問卷調(diào)查應(yīng)用程序現(xiàn)已創(chuàng)建完成。確保 mongod 仍在運行,并在 Eclipse 中再次運行 Node 應(yīng)用程序。在瀏覽器中輸入 http://localhost:3000,導(dǎo)航到一個問卷調(diào)查并進(jìn)行投票。隨后您就可以看到結(jié)果。要查看實時更新,請找到您的本地 IP 地址,并用該地址替換 localhost 。在您的局域網(wǎng)中,使用不同的機(jī)器(甚至智能手機(jī)或平板電腦也可以)導(dǎo)航到這個地址。當(dāng)您在另一個設(shè)備上進(jìn)行投票時,結(jié)果會顯示在該設(shè)備上,而且會自動發(fā)布到您的主要計算機(jī)瀏覽器上:

圖 4. 查看問卷調(diào)查結(jié)果


回頁首

下一步:進(jìn)一步開發(fā)和部署

您剛才創(chuàng)建的這個問卷調(diào)查應(yīng)用程序是一個不錯的起點,但還有很大的改進(jìn)空間。在計劃創(chuàng)建這類應(yīng)用程序時,我喜歡使用一種敏捷方法來定義用戶案例,并將項目劃分為幾塊來實現(xiàn)。對于這個項目,我使用了 JazzHub,通過將項目的附屬代碼和源代碼一起保存在一個云托管的存儲庫中,JazzHub 使得開發(fā)變得非常簡單。

如果您對您的應(yīng)用程序感到很滿意,下一步就是跟全世界的人分享它。在過去,即使部署一個非常簡單的應(yīng)用程序,可能也會是一場噩夢,但值得慶幸的是,那些日子已經(jīng)一去不復(fù)返了。使用 IBM 新興的兼容 Cloud Foundry 的BlueMix平臺,您只需幾分鐘就可以通過最少的配置將您的應(yīng)用程序部署到云中,一點都不麻煩。


回頁首

結(jié)束語

這對于開發(fā)人員,現(xiàn)在是一個很好的時機(jī)。我們手頭有大量框架和工具,它們使得開發(fā)大量應(yīng)用程序不僅更簡單、更快速,而且更加令人感到愉快。在本文中,您學(xué)習(xí)了如何使用被稱為 MEAN 體系結(jié)構(gòu)(Mongo、Express、Angular 和Node)的技術(shù)構(gòu)建一個應(yīng)用程序。該堆棧可能只需要一天時間就可以完成任務(wù),遠(yuǎn)遠(yuǎn)超過了 LAMP 體系結(jié)構(gòu)(Linux、Apache、MySQL 和 PHP),在 Web 應(yīng)用程序開發(fā)和部署方面,該體系結(jié)構(gòu)也許同樣會超越 LAMP 體系結(jié)構(gòu)。對我而言,我已經(jīng)迫不及待躍躍欲試了。

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
AngularJS學(xué)習(xí)筆記
通過 AngularJS 和 ASP.NET MVC5 實現(xiàn)文件上傳
angularjs上傳多張圖片并預(yù)覽
Angular移除不必要的$watch之性能優(yōu)化
Angularjs十大經(jīng)典面試題
Angular開發(fā)中的注意事項
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服