使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)
前篇
使用React、Node.js、MongoDB、Socket.IO開發(fā)一個角色投票應(yīng)用的學(xué)習(xí)過程(一)
使用React、Node.js、MongoDB、Socket.IO開發(fā)一個角色投票應(yīng)用的學(xué)習(xí)過程(二)
原文第十三步,Express API路由
第一個路由是用來創(chuàng)建角色的
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 匿名函數(shù)變成了ES6的'=>'箭頭函數(shù),雖然我用的是warterline而原文中用的是mongoose但是包括方法名基本都一樣,所以我感覺waterline是在API上最接近mongoose
順便說一下,我為什么不喜歡mongodb,僅僅是因?yàn)橛幸淮挝野惭b了,只往里面寫了幾條測試數(shù)據(jù),按文本算最多幾kb,但第二天重啟機(jī)器的時候,系統(tǒng)提示我,我的/home分區(qū)空間不足了(雙系統(tǒng)分區(qū)分給linux分小了本來就不大),結(jié)果一查mongodb 的data文件 有2G多,我不知道什么原因,可能是配置不對還是別的什么原因,反正,當(dāng)天我就把它刪除了,
完成了這個API我們就可以往數(shù)據(jù)庫里添加?xùn)|西了,不知道哪些用戶名可以用?相當(dāng)簡單,反正我用的全是一名人的名字(英文名),外國人也喜歡搶注名字,嘿嘿嘿
原文第十三步,Home組件
基本保持和原文一樣,只是用lodash 替換了 underscore
一開始我看到網(wǎng)上介紹lodash是可以無縫替換underscore,中要修改引用就可以,但是我用的版本是4.11.2已經(jīng)有很多方法不一樣了,還去掉了不少方法(沒有去關(guān)注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中已經(jīng)不存正,我用了filter來實(shí)現(xiàn)相同功能。
第十四步:Express API 路由(2/2)
GET /api/characters
原文的實(shí)現(xiàn)方法
/*** 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] } }做為查詢條件從而在數(shù)據(jù)庫里取出兩條隨機(jī)的記錄返回給頁面進(jìn)行PK,前文說過random的類型在mysql沒有類似的,所以我把這個字段刪除了。本來mysql,可以用order by rand() 之類的方法但是,waterline的sort(order by rand())不被支持,所以我是把所有符合條件的記錄取出來,能過lodash的sampleSize方法從所有記錄中獲取兩天隨機(jī)記錄。
app.get('/api/characters', (req,res,next) => {let choice = ['Female', 'Male'];let randomGender = _.sample(choice);//原文中是通過nearby字段來實(shí)現(xiàn)隨機(jī)取值,waterline沒有實(shí)現(xiàn)mysql order by rand()返回隨機(jī)記錄,所以返回所有結(jié)果,用lodash來處理app.models.character.find().where({'voted': false}).exec((err,characters) => {if(err) return next(err);//用lodash來取兩個隨機(jī)值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([]);});});});在數(shù)據(jù)量大的情況下,這個的方法性能上肯定會有問題,好在我們只是學(xué)習(xí)過程,數(shù)據(jù)量也不大。將就用一下,能實(shí)現(xiàn)相同的功能就可以了。
GET /api/characters/search
這個API之前還有兩個API,和原文基本一樣,所做的修改只是用了ES6的語法,就不浪費(fèi)篇幅了,可以去我的github看
這一個也只是一點(diǎn)mongoose和waterline的一點(diǎn)點(diǎn)小區(qū)別
原文中mongoose的模糊查找是用正則來做的,mysql好像也可以,但是warterline中沒有找到相關(guān)方法(它的文檔太簡陋了)
所以原文中
我改成了
app.get('/api/characters/search', (req,res,next) => {app.models.character.findOne({name:{'contains':req.query.name}}, (err,character) => {.....通過contains來查找,其實(shí)就是like %sometext%的方法來實(shí)現(xiàn)
下面還有兩個方法修改的地方也大同小異,就不仔細(xì)講了,看代碼吧
GET /api/stats
這個是原文最后一個路由了,
原文中用了一串的函數(shù)來獲取各種統(tǒng)計(jì)信息,原作者也講了可以優(yōu)化,哪我們就把它優(yōu)化一下吧
我把要統(tǒng)計(jì)數(shù)據(jù)的字段放入一個數(shù)組countColumn通過forEach把push到asyncTask,最后兩個統(tǒng)計(jì)方法不一樣的函數(shù),單獨(dú)push,最后用async.parallel方法執(zhí)行并獲得結(jié)果。
underscore的max方法可以從{a:1,b:6,d:2,e:3}返回最大值,但是lodash新版中的不行,只能通過_.max(_.values(bloodlineCount))這樣的方式返回最大值。
總結(jié)
以上是生活随笔為你收集整理的使用React、Node.js、MongoDB、Socket.IO开发一个角色投票应用的学习过程(三)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怀孕梦到很多鸡蛋是什么意思
- 下一篇: 梦到妈妈开车我坐车好不好