## 第十三步:Express API 路由(1/2)
在这一节我们将实现一个Express路由,以获取角色信息并存储进数据库。我们将使用[EVE Online API](http://wiki.eve-id.net/APIv2_Page_Index)来获取给定character name的Character ID,Race以及Bloodline。
> 注意:角色性别并不是公开数据,它需要一个API key。在我看来,让New Eden
> Faces变得非常棒的是它的开放生态:用户并不需要登录即可添加、查看EVE中的角色。这也是为什么我在表单里添加了性别选项让用户自己填写的缘故,虽
> 然它的准确性的确依赖于用户的诚信。
下面的表格列出了每个路由的职责。不过,我们不会实现所有的路由,如果需要的话你可以自己实现它们。
| Route | POST | GET | PUT | DELETE |
| --- | --- | --- | --- | --- |
| /api/characters | 添加新角色 | 获取随机两个角色 | 更新角色投票胜负信息 | 删除所有角色 |
| /api/characters/:id | N/A | 获取角色 | 更新角色 | 删除角色 |
在server.js文件前面添加下列依赖:
~~~
var async = require('async');var request = require('request');
~~~
我们将使用[`async.waterfall`](https://github.com/caolan/async#waterfalltasks-callback)来管理多异步操作,使用request来向EVE Online API发起HTTP请求。
将我们的第一个路由添加到Express中间件后面,在第8步创建的React中间件前面:
~~~
/**
* POST /api/characters
* Adds new character to the database.
*/
app.post('/api/characters', function(req, res, next) {
var gender = req.body.gender;
var characterName = req.body.name;
var characterIdLookupUrl = 'https://api.eveonline.com/eve/CharacterID.xml.aspx?names=' + characterName;
var parser = new xml2js.Parser();
async.waterfall([
function(callback) {
request.get(characterIdLookupUrl, function(err, request, xml) {
if (err) return next(err);
parser.parseString(xml, function(err, parsedXml) {
if (err) return next(err);
try {
var characterId = parsedXml.eveapi.result[0].rowset[0].row[0].$.characterID;
Character.findOne({ characterId: characterId }, function(err, character) {
if (err) return next(err);
if (character) {
return res.status(409).send({ message: character.name + ' is already in the database.' });
}
callback(err, characterId);
});
} catch (e) {
return res.status(400).send({ message: 'XML Parse Error' });
}
});
});
},
function(characterId) {
var characterInfoUrl = 'https://api.eveonline.com/eve/CharacterInfo.xml.aspx?characterID=' + characterId;
request.get({ url: characterInfoUrl }, function(err, request, xml) {
if (err) return next(err);
parser.parseString(xml, function(err, parsedXml) {
if (err) return res.send(err);
try {
var name = parsedXml.eveapi.result[0].characterName[0];
var race = parsedXml.eveapi.result[0].race[0];
var bloodline = parsedXml.eveapi.result[0].bloodline[0];
var character = new Character({
characterId: characterId,
name: name,
race: race,
bloodline: bloodline,
gender: gender,
random: [Math.random(), 0]
});
character.save(function(err) {
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.' });
}
});
});
}
]);
});
~~~
> 注意:我一般在路由上面写块级注释,包括完整路径和简介,这样我就能使用查找功能(Command+F)来快速寻找路由,如下图所示:
![](https://box.kancloud.cn/2015-09-14_55f643ecdf702.jpg)
下面就来按部就班的看一下它是如何工作的:
1. 利用Character Name获取Character ID。
![](https://box.kancloud.cn/2015-09-14_55f643ed7c76e.jpg)
2. 解析XML响应。
3. 查询数据库看这个角色是否已经存在。
4. 将Character ID传递给`async.waterfall`中的下一个函数。
5. 利用Character ID获取基本的角色信息。
![](https://box.kancloud.cn/2015-09-14_55f643ef6d840.jpg)
6. 解析XML响应。
7. 添加新角色到数据库。
在浏览器打开[http://localhost:3000/add](http://localhost:3000/add) 并添加一些角色,你可以使用下面的名字:
* Daishan Auergni
* CCP Falcon
* Celeste Taylor
![](https://box.kancloud.cn/2015-09-14_55f643eff052d.jpg)
或者,你也可以下载这个MongoDB文件dump并将它导入到你的数据库,它包含4000以上个角色。如果你之前添加了其中的一些角色,可能会出现“duplicate key errors”错误,不用管它:
* [newedenfaces.bson](https://dl.dropboxusercontent.com/u/14131013/newedenfaces.bson)
下载之后使用下面的命令将它导入到数据库:
~~~
$ mongorestore newedenfaces.bson
~~~
鉴于我们还没有实现相关的API,现在你还不能看到总的角色数,我们将在下下节来实现。
下面让我们先创建Home组件,这是一个初始页面,上面会并排显示两个角色。
(*译者注:下面会先第15节再第14节,原文如此*)
- 前言
- 概述
- 第一步:新建Express项目
- 第二步:构建系统
- 第三步:项目结构
- 第四步: ES6速成教程
- 第五步: React速成教程
- 第六步:Flux架构速成教程
- 第七步:React路由(客户端)
- 第八步:React路由(服务端)
- 第九步:Footer和Navbar组件
- 第十步:Socke.IO – 实时用户数
- 第十一步:添加Character的组件
- 第十二步:数据库模式
- 第十三步:Express API 路由(1/2)
- 第十五步:Home组件
- 第十四步:Express API 路由(2/2)
- 第十六步:角色(资料)组件
- 第十七步:Top 100 组件
- 第十八步:Stats组件
- 第十九步:部署
- 第二十步: 附加资源
- 总结