日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)

發布時間:2023/11/29 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前篇

使用React、Node.js、MongoDB、Socket.IO開發一個角色投票應用的學習過程(一)
使用React、Node.js、MongoDB、Socket.IO開發一個角色投票應用的學習過程(二)

原文第十三步,Express API路由

第一個路由是用來創建角色的

app.post('/api/characters',(req,res,next) => {let gender = req.body.gender;let characterName = req.body.name;let characterIdLookupUrl = 'https://api.eveonline.com/eve/CharacterId.xml.aspx?names=' + characterName;const parser = new xml2js.Parser();async.waterfall([function(callback) {request.get(characterIdLookupUrl,(err,request,xml) => {if(err) return next(err);parser.parseString(xml,(err,parsedXml) => {try {let characterId = parsedXml.eveapi.result[0].rowset[0].row[0].$.characterID;app.models.character.findOne({ characterId: characterId},(err,model) => {if(err) return next(err);if(model) {return res.status(400).send({ message: model.name + ' is alread in the database'});}callback(err,characterId);});} catch(e) {return res.status(400).send({ message: ' xml Parse Error'});}});});},function(characterId) {let characterInfoUrl = 'https://api.eveonline.com/eve/CharacterInfo.xml.aspx?characterID=' + characterId;console.log(characterInfoUrl);request.get({ url: characterInfoUrl },(err,request,xml) => {if(err) return next(err);parser.parseString(xml, (err,parsedXml) => {if (err) return res.send(err);try{let name = parsedXml.eveapi.result[0].characterName[0];let race = parsedXml.eveapi.result[0].race[0];let bloodline = parsedXml.eveapi.result[0].bloodline[0];app.models.character.create({characterId: characterId,name: name,race: race,bloodline: bloodline,gender: gender},(err,model) => {if(err) return next(err);res.send({ message: characterName + ' has been added successfully!'});});} catch (e) {res.status(404).send({ message: characterName + ' is not a registered citizen of New Eden',error: e.message });}});});}]); });

是不是看起來和原文的基本一模一樣,只不過把var 變成了let 匿名函數變成了ES6的'=>'箭頭函數,雖然我用的是warterline而原文中用的是mongoose但是包括方法名基本都一樣,所以我感覺waterline是在API上最接近mongoose

順便說一下,我為什么不喜歡mongodb,僅僅是因為有一次我安裝了,只往里面寫了幾條測試數據,按文本算最多幾kb,但第二天重啟機器的時候,系統提示我,我的/home分區空間不足了(雙系統分區分給linux分小了本來就不大),結果一查mongodb 的data文件 有2G多,我不知道什么原因,可能是配置不對還是別的什么原因,反正,當天我就把它刪除了,

完成了這個API我們就可以往數據庫里添加東西了,不知道哪些用戶名可以用?相當簡單,反正我用的全是一名人的名字(英文名),外國人也喜歡搶注名字,嘿嘿嘿

原文第十三步,Home組件

基本保持和原文一樣,只是用lodash 替換了 underscore

一開始我看到網上介紹lodash是可以無縫替換underscore,中要修改引用就可以,但是我用的版本是4.11.2已經有很多方法不一樣了,還去掉了不少方法(沒有去關注underscore是不是也在最新版本中有同樣的改動)

原文中:

...... import {first, without, findWhere} from 'underscore'; ......var loser = first(without(this.state.characters, findWhere(this.state.characters, { characterId: winner }))).characterId;......

修改為:

...... import {first, filter} from 'lodash'; ......let loser = first(filter(this.state.characters,item => item.characterId != winner )).characterId;

findWhere 在最新版本的lodash中已經不存正,我用了filter來實現相同功能。

第十四步:Express API 路由(2/2)

GET /api/characters

原文的實現方法

/*** GET /api/characters* Returns 2 random characters of the same gender that have not been voted yet.*/ app.get('/api/characters', function(req, res, next) {var choices = ['Female', 'Male'];var randomGender = _.sample(choices);Character.find({ random: { $near: [Math.random(), 0] } }).where('voted', false).where('gender', randomGender).limit(2).exec(function(err, characters) {if (err) return next(err);if (characters.length === 2) {return res.send(characters);}var oppositeGender = _.first(_.without(choices, randomGender));Character.find({ random: { $near: [Math.random(), 0] } }).where('voted', false).where('gender', oppositeGender).limit(2).exec(function(err, characters) {if (err) return next(err);if (characters.length === 2) {return res.send(characters);}Character.update({}, { $set: { voted: false } }, { multi: true }, function(err) {if (err) return next(err);res.send([]);});});}); });

可以看到原文中用{ random: { $near: [Math.random(), 0] } }做為查詢條件從而在數據庫里取出兩條隨機的記錄返回給頁面進行PK,前文說過random的類型在mysql沒有類似的,所以我把這個字段刪除了。本來mysql,可以用order by rand() 之類的方法但是,waterlinesort(order by rand())不被支持,所以我是把所有符合條件的記錄取出來,能過lodashsampleSize方法從所有記錄中獲取兩天隨機記錄。

app.get('/api/characters', (req,res,next) => {let choice = ['Female', 'Male'];let randomGender = _.sample(choice);//原文中是通過nearby字段來實現隨機取值,waterline沒有實現mysql order by rand()返回隨機記錄,所以返回所有結果,用lodash來處理app.models.character.find().where({'voted': false}).exec((err,characters) => {if(err) return next(err);//用lodash來取兩個隨機值let randomCharacters = _.sampleSize(_.filter(characters,{'gender': randomGender}),2); if(randomCharacters.length === 2){//console.log(randomCharacters);return res.send(randomCharacters);}//換個性別再試試let oppsiteGender = _.first(_.without(choice, randomGender));let oppsiteCharacters = _.sampleSize(_.filter(characters,{'gender': oppsiteGender}),2); if(oppsiteCharacters === 2) {return res.send(oppsiteCharacters);}//沒有符合條件的character,就更新voted字段,開始新一輪PKapp.models.character.update({},{'voted': false}).exec((err,characters) => {if(err) return next(err);return res.send([]);});});});

在數據量大的情況下,這個的方法性能上肯定會有問題,好在我們只是學習過程,數據量也不大。將就用一下,能實現相同的功能就可以了。

GET /api/characters/search

這個API之前還有兩個API,和原文基本一樣,所做的修改只是用了ES6的語法,就不浪費篇幅了,可以去我的github看

這一個也只是一點mongoosewaterline的一點點小區別
原文中mongoose的模糊查找是用正則來做的,mysql好像也可以,但是warterline中沒有找到相關方法(它的文檔太簡陋了)
所以原文中

app.get('/api/characters/search', function(req, res, next) {var characterName = new RegExp(req.query.name, 'i');Character.findOne({ name: characterName }, function(err, character) {......

我改成了

app.get('/api/characters/search', (req,res,next) => {app.models.character.findOne({name:{'contains':req.query.name}}, (err,character) => {.....

通過contains來查找,其實就是like %sometext%的方法來實現
下面還有兩個方法修改的地方也大同小異,就不仔細講了,看代碼吧

GET /api/stats

這個是原文最后一個路由了,
原文中用了一串的函數來獲取各種統計信息,原作者也講了可以優化,哪我們就把它優化一下吧

app.get('/api/stats', (req,res,next) => {let asyncTask = [];let countColumn = [{},{race: 'Amarr'},{race: 'Caldari'},{race: 'Gallente'},{race: 'Minmatar'},{gender: 'Male'},{gender: 'Female'}];countColumn.forEach(column => {asyncTask.push( callback => {app.models.character.count(column,(err,count) => {callback(err,count);});})});asyncTask.push(callback =>{app.models.character.find().sum('wins').then(results => {callback(null,results[0].wins);});} );asyncTask.push(callback => {app.models.character.find().sort('wins desc').limit(100).select('race').exec((err,characters) => {if(err) return next(err);let raceCount = _.countBy(characters,character => character.race);console.log(raceCount);let max = _.max(_.values(raceCount));console.log(max);let inverted = _.invert(raceCount);let topRace = inverted[max];let topCount = raceCount[topRace];callback(err,{race: topRace, count: topCount});});});asyncTask.push(callback => {app.models.character.find().sort('wins desc').limit(100).select('bloodline').exec((err,characters) => {if(err) return next(err);let bloodlineCount = _.countBy(characters,character => character.bloodline);let max = _.max(_.values(bloodlineCount));let inverted = _.invert(bloodlineCount);let topBloodline = inverted[max];let topCount = bloodlineCount[topBloodline];callback(err,{bloodline: topBloodline, count: topCount});});});async.parallel(asyncTask,(err,results) => {if(err) return next(err);res.send({totalCount: results[0],amarrCount: results[1],caldariCount: results[2],gallenteCount: results[3],minmatarCount: results[4],maleCount: results[5],femaleCount: results[6],totalVotes: results[7],leadingRace: results[8],leadingBloodline:results[9]});}) });

我把要統計數據的字段放入一個數組countColumn通過forEach把push到asyncTask,最后兩個統計方法不一樣的函數,單獨push,最后用async.parallel方法執行并獲得結果。

underscore的max方法可以從{a:1,b:6,d:2,e:3}返回最大值,但是lodash新版中的不行,只能通過_.max(_.values(bloodlineCount))這樣的方式返回最大值。

總結

以上是生活随笔為你收集整理的使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。