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

2021-10-23 14:32 更新

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

在这一节我们将实现一个Express路由,以获取角色信息并存储进数据库。我们将使用EVE Online API来获取给定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来管理多异步操作,使用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)来快速寻找路由,如下图所示:

下面就来按部就班的看一下它是如何工作的:

  1. 利用Character Name获取Character ID。
  2. 解析XML响应。
  3. 查询数据库看这个角色是否已经存在。
  4. 将Character ID传递给async.waterfall中的下一个函数。
  5. 利用Character ID获取基本的角色信息。
  6. 解析XML响应。
  7. 添加新角色到数据库。

在浏览器打开http://localhost:3000/add 并添加一些角色,你可以使用下面的名字:

  • Daishan Auergni
  • CCP Falcon
  • Celeste Taylor

或者,你也可以下载这个MongoDB文件dump并将它导入到你的数据库,它包含4000以上个角色。如果你之前添加了其中的一些角色,可能会出现“duplicate key errors”错误,不用管它:

下载之后使用下面的命令将它导入到数据库:

$ mongorestore newedenfaces.bson

鉴于我们还没有实现相关的API,现在你还不能看到总的角色数,我们将在下下节来实现。

下面让我们先创建Home组件,这是一个初始页面,上面会并排显示两个角色。

译者注:下面会先第15节再第14节,原文如此

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号