摘要:將就用一下,能實現相同的功能就可以了。的方法可以從返回最大值,但是新版中的不行,只能通過這樣的方式返回最大值。
前篇
原文第十三步,Express API路由使用React、Node.js、MongoDB、Socket.IO開發一個角色投票應用的學習過程(一)
使用React、Node.js、MongoDB、Socket.IO開發一個角色投票應用的學習過程(二)
第一個路由是用來創建角色的
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;
第十四步:Express API 路由(2/2) GET /api/charactersfindWhere 在最新版本的lodash中已經不存正,我用了filter來實現相同功能。
原文的實現方法
/** * 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() 之類的方法但是,waterline的sort(order by rand())不被支持,所以我是把所有符合條件的記錄取出來,能過lodash的sampleSize方法從所有記錄中獲取兩天隨機記錄。
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字段,開始新一輪PK app.models.character.update({},{"voted": false}).exec((err,characters) => { if(err) return next(err); return res.send([]); }); }); });
GET /api/characters/search在數據量大的情況下,這個的方法性能上肯定會有問題,好在我們只是學習過程,數據量也不大。將就用一下,能實現相同的功能就可以了。
這個API之前還有兩個API,和原文基本一樣,所做的修改只是用了ES6的語法,就不浪費篇幅了,可以去我的github看
這一個也只是一點mongoose和waterline的一點點小區別
原文中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%的方法來實現
下面還有兩個方法修改的地方也大同小異,就不仔細講了,看代碼吧
這個是原文最后一個路由了,
原文中用了一串的函數來獲取各種統計信息,原作者也講了可以優化,哪我們就把它優化一下吧
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))這樣的方式返回最大值。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/79433.html
摘要:吐完槽,還是開始第十二部分的改動吧,這是開始涉及到數據庫了,原文用我用改動就比較大了。后篇使用開發一個角色投票應用的學習過程三 前篇 使用React、Node.js、MongoDB、Socket.IO開發一個角色投票應用的學習過程(一) 這篇主要講一下waterline的初始化,原文用的是mongoose 原文第十二步 一下子就到十二步了,因為原文件中react部分的代碼本來就是用E...
摘要:本項目是對使用開發一個角色投票應用的學習過程。到這里為止沒有遇到多大的坑,最多的往往是拼寫錯誤引起的問題,唯一由于拼寫導致,但不提示錯誤的是我打成了運行的時候服務器一直沒有響應,找了好久才找到這個錯誤后篇使用開發一個角色投票應用的學習過程二 本項目是對使用React、Node.js、MongoDB、Socket.IO開發一個角色投票應用的學習過程。 英文原文:Create a char...
摘要:異步最佳實踐避免回調地獄前端掘金本文涵蓋了處理異步操作的一些工具和技術和異步函數。 Nodejs 連接各種數據庫集合例子 - 后端 - 掘金Cassandra Module: cassandra-driver Installation ... 編寫 Node.js Rest API 的 10 個最佳實踐 - 前端 - 掘金全文共 6953 字,讀完需 8 分鐘,速讀需 2 分鐘。翻譯自...
摘要:鑒于此目的,我決定快速構建一個用于此目的的問卷調查應用程序。這將啟動一個服務器并將應用程序部署到該服務器。圖應用程序配置基礎前端這個問卷調查應用程序對常見用戶界面和布局使用了框架。 全棧教程。轉自 使用 Node.js、Express、AngularJS 和 MongoDB 構建一個實時問卷調查應用程序 最近,在向大學生們介紹 HTML5 的時候,我想要對他們進行問卷調查,并向他們顯...
閱讀 3063·2021-11-24 10:34
閱讀 3322·2021-11-22 13:53
閱讀 2630·2021-11-22 12:03
閱讀 3598·2021-09-26 09:47
閱讀 3005·2021-09-23 11:21
閱讀 4772·2021-09-22 15:08
閱讀 3289·2021-07-23 10:59
閱讀 1258·2019-08-29 18:31