Node.js实现RESTful api,express or koa?
<p>文章导读:</p><ul>
<li> 一、what's RESTful API</li>
<li> 二、Express RESTful API</li>
<li> 三、KOA RESTful API</li>
<li> 四、express还是koa? </li>
<li> 五、参考资料 </li>
</ul>
<p> </p>
<h3>一、what's RESTful API</h3>
<p><strong>1.1 RESTful架构</strong></p>
<p> 要理解什么是RESTful API我们可以先看一下什么是RESTful架构。</p>
<p> REST是Representational State Transfer的缩写,我们可以理解为它的含义是“表现层状态转化”,wikipedia是这样说的:“an architectural style that abstracts the architectural elements within a distributed hypermedia system”,这就是REST互联网软件的架构原则。</p>
<p> 我们可以说如果一个架构符合REST原则,就称它为RESTful架构。</p>
<p><strong>1.2 RESTful API</strong></p>
<p> 那么回到我们的RESTful api,我们为了有一种统一的机制,方便不同的前端设备与后端进行通信于是便有了 RESTful API这一套目前比较成熟的互联网应用程序的API设计理论。那么我们为了设计一个合理,好用的api,需要做些什么呢?简单的说大致需要做到以下几点:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> 1<span style="color: rgba(0, 0, 0, 1)">. api与用户的通信协议总是使用HTTPs
</span><span style="color: rgba(0, 128, 128, 1)">2</span> 2. 我们尽量将API部署在专用域名下:https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">api.example.com</span>
<span style="color: rgba(0, 128, 128, 1)">3</span> 3. url中有标示api版本号的字段:https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">api.example.com/v1/</span>
<span style="color: rgba(0, 128, 128, 1)">4</span> 4. 路径带有明确的含义:https:<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">api.example.com/v1/animals</span>
<span style="color: rgba(0, 128, 128, 1)">5</span> 5. 明确资源的具体操作类型,使用相应的HTTP方法:GET/POST/PUT/DELETE/<span style="color: rgba(0, 0, 0, 1)">PATCH
</span><span style="color: rgba(0, 128, 128, 1)">6</span> 6. api中提供过滤信息的参数:?page=2&per_page=100<span style="color: rgba(0, 0, 0, 1)">:指定第几页,以及每页的记录数
</span><span style="color: rgba(0, 128, 128, 1)">7</span> 7. 请求api后服务器需要返回明确的状态码,如果出错,带有错误处理</pre>
</div>
<p> 其实我们可以简单的理解为RESTful API就是更加规范的API。</p>
<p> 下面我们就可以开始基于Nodejs的express和koa来实现一些例子理解下RESTful API。</p>
<h3>二、Express RESTful API</h3>
<p><strong>2.1简单的get数据库中的数据 </strong></p>
<p>我们先通过一个简单些的只get获取数据库中数据的例子开始:</p>
<p>2.1.1 准备工作: <br> 确认我们已经安装了nodejs express;<br> install mongodb数据库mac;<br>2.1.2 先开始最简单的例子:<br> 目录结构,data是数据库相关的目录,我们可以先忽略掉:</p>
<p> <img src="https://images0.cnblogs.com/blog2015/546321/201508/281400405152250.png" alt=""></p>
<p> 确保我们的package.json文件中有mongodb等依赖:</p>
<div class="cnblogs_code"><img id="code_img_closed_73c92e03-d139-4d2e-a995-6464c20f5634" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_73c92e03-d139-4d2e-a995-6464c20f5634" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_73c92e03-d139-4d2e-a995-6464c20f5634" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> "name":"node-api"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> "main":"server.js"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> "dependencies"<span style="color: rgba(0, 0, 0, 1)">:{
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> "express":"~4.0.0"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> "mongoose":"~3.6.13"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> "body-parser":"~1.0.1"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> "morgan":"~1.5.3"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> "mongodb":"~2.0.33"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">10</span> "monk":"~1.0.1"
<span style="color: rgba(0, 128, 128, 1)">11</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">12</span> }</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> 在server.js中定义简单的路由和进行数据库操作:</p>
<div class="cnblogs_code"><img id="code_img_closed_a4cb01df-8be6-4b4d-ba21-bab223856a04" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_a4cb01df-8be6-4b4d-ba21-bab223856a04" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_a4cb01df-8be6-4b4d-ba21-bab223856a04" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">var</span> express = require('express'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)">var</span> app =<span style="color: rgba(0, 0, 0, 1)"> express();
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">var</span> bodyParser = require('body-parser'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 255, 1)">var</span> path = require('path'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">database</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">var</span> mongo = require('mongodb'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">var</span> monk = require('monk'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 255, 1)">var</span> db = monk('localhost:27017/restdata'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span>
<span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">app.use()里面没有函数</span>
<span style="color: rgba(0, 128, 128, 1)">11</span> app.use(bodyParser.urlencoded({ extended : <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">}));
</span><span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 0, 1)">app.use(bodyParser.json());
</span><span style="color: rgba(0, 128, 128, 1)">13</span>
<span style="color: rgba(0, 128, 128, 1)">14</span> app.use(express.static(__dirname+'/public'<span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 128, 1)">15</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 255, 1)">var</span> collectorder = db.get('orderlist'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 255, 1)">var</span> collectuser = db.get('userlist'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">18</span>
<span style="color: rgba(0, 128, 128, 1)">19</span>
<span style="color: rgba(0, 128, 128, 1)">20</span> app.get('/orders',<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(req,res){
</span><span style="color: rgba(0, 128, 128, 1)">21</span> collectorder.find({},{limit:20},<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err,orders){
</span><span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 0, 0, 1)"> res.json(orders);
</span><span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 128, 128, 1)">25</span> app.get('/users',<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(req,res){
</span><span style="color: rgba(0, 128, 128, 1)">26</span> collectuser.find({},{},<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err,users){
</span><span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 0, 1)"> res.json(users);
</span><span style="color: rgba(0, 128, 128, 1)">28</span> <span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 128, 128, 1)">30</span>
<span style="color: rgba(0, 128, 128, 1)">31</span> app.get('/users/:name',<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(req,res){
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">var collection = db.get(req.params.name);</span>
<span style="color: rgba(0, 128, 128, 1)">33</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">console.log(req.params.name);</span>
<span style="color: rgba(0, 128, 128, 1)">34</span> collectuser.find({name:req.params.name},{},<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err,docs){
</span><span style="color: rgba(0, 128, 128, 1)">35</span> <span style="color: rgba(0, 0, 0, 1)"> res.json(docs);
</span><span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 0, 0, 1)">});
</span><span style="color: rgba(0, 128, 128, 1)">38</span>
<span style="color: rgba(0, 128, 128, 1)">39</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">客户端通过请求adduser接口post数据进入数据库</span>
<span style="color: rgba(0, 128, 128, 1)">40</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> app.post('/adduser',function(req,res){</span>
<span style="color: rgba(0, 128, 128, 1)">41</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> var db = req.db;</span>
<span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> collectuser.insert(req.body,function(err,result){</span>
<span style="color: rgba(0, 128, 128, 1)">43</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> res.send(</span>
<span style="color: rgba(0, 128, 128, 1)">44</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> (err == null) ? {msg:''}:{msg:err}</span>
<span style="color: rgba(0, 128, 128, 1)">45</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> );</span>
<span style="color: rgba(0, 128, 128, 1)">46</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> });</span>
<span style="color: rgba(0, 128, 128, 1)">47</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> });</span>
<span style="color: rgba(0, 128, 128, 1)">48</span>
<span style="color: rgba(0, 128, 128, 1)">49</span>
<span style="color: rgba(0, 128, 128, 1)">50</span>
<span style="color: rgba(0, 128, 128, 1)">51</span>
<span style="color: rgba(0, 128, 128, 1)">52</span> app.listen(3000);</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> 数据库操作:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> mongod --dbpath c:\node\nodetest2\data (项目中data目标路径)</pre>
</div>
<p> 新开一个控制台窗口运行:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)">mongo
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 0, 1)">use nodetest2(意义上的数据库名称)
</span><span style="color: rgba(0, 128, 128, 1)">3</span> db.userlist.insert({'username' : 'test1','email' : 'test1@test.com','fullname' : 'Bob Smith','age' : 27,'location' : 'San Francisco','gender' : 'Male'<span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 128, 128, 1)">4</span> 我们可以查看<span style="color: rgba(0, 128, 0, 1)"> 的api,查看数据库的操作方法</span></pre>
</div>
<p> 如果没有什么问题的话,两个控制台窗口应该是这样的:</p>
<p><img src="https://images0.cnblogs.com/blog2015/546321/201508/281406185472687.png" alt=""></p>
<p> 运行实例: </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> node server.js</pre>
</div>
<p> 访问url就可以看到我们获取到了的数据:</p>
<p><img src="https://images0.cnblogs.com/blog2015/546321/201508/281408082818610.png" alt=""></p>
<p> [查看项目源码]</p>
<p> </p>
<p><strong>2.2 使用express实现数据交互(get/post/delete)</strong></p>
<p><strong> </strong>实际上,我们刚才的例子并不算是一个完整的express的项目。我们只是用到了其中的几个API。我们通过express-generator生成的express项目的脚手架应该是这个样子的:</p>
<p> <img src="https://images0.cnblogs.com/blog2015/546321/201508/281429071401333.png" alt=""></p>
<p> 我们可以看到入口的app.js文件,以及控制路由的routes和控制显示的views文件夹,里面存放了jade模板的文件。很好地组织了项目的目录。</p>
<p> 可以从express官方github开始,快速上手express:.</p>
<p> 这里说的数据交互的例子,有个非常详细易懂的教程:</p>
<p> 然而也可以直接获取我仓库中的项目源代码:</p>
<h3>三、KOA RESTful API</h3>
<p><strong>3.1 简单get数据</strong><br> 同样,koa版本我们也从最简单的实例开始。<br> 1.目录结构,同样,我们也先忽略跟数据库相关的data文件夹:</p>
<p> <img src="https://images0.cnblogs.com/blog2015/546321/201508/281412227977900.png" alt=""><br> 2.确保我们的package.json文件中依赖了koa koa-route mongoose 和monk等:</p>
<div class="cnblogs_code"><img id="code_img_closed_b9dbabb1-a022-414e-b8b8-e6f87adcb548" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_b9dbabb1-a022-414e-b8b8-e6f87adcb548" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_b9dbabb1-a022-414e-b8b8-e6f87adcb548" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> "name": "koarestapi"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> "version": "0.0.1"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> "description": ""<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> "main": "app.js"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> "dependencies"<span style="color: rgba(0, 0, 0, 1)">: {
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> "co-body": "~0.0.1"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> "co-monk": "~0.0.1"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> "koa": "~0.1.2"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">10</span> "koa-route": "~1.0.2"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">11</span> "koa-router": "~2.2.0"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">12</span> "kongo": "~0.0.3"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">13</span> "mongoose": "~3.8.3"<span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">14</span> "monk": "~0.7.1"
<span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 0, 1)">},
</span><span style="color: rgba(0, 128, 128, 1)">16</span> "author": "yixuan"
<span style="color: rgba(0, 128, 128, 1)">17</span> }</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> 3.同样在app.js中定义koa版本的路由和简单的数据库操作:</p>
<div class="cnblogs_code"><img id="code_img_closed_3e49f4a0-3ac3-49e8-84be-798385b002c8" class="code_img_closed" src="https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif" alt=""><img id="code_img_opened_3e49f4a0-3ac3-49e8-84be-798385b002c8" class="code_img_opened" style="display: none" src="https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif" alt="">
<div id="cnblogs_code_open_3e49f4a0-3ac3-49e8-84be-798385b002c8" class="cnblogs_code_hide">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <span style="color: rgba(0, 0, 255, 1)">var</span> koa = require('koa'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)">var</span> route = require('koa-route'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">var</span> app = module.exports =<span style="color: rgba(0, 0, 0, 1)"> koa();
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 255, 1)">var</span> monk = require('monk'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> <span style="color: rgba(0, 0, 255, 1)">var</span> wrap = require('co-monk'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> <span style="color: rgba(0, 0, 255, 1)">var</span> db = monk('localhost:27017/apitest'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 255, 1)">var</span> books = wrap(db.get('books'<span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span>
<span style="color: rgba(0, 128, 128, 1)"> 9</span> app.use(route.get('/book'<span style="color: rgba(0, 0, 0, 1)">,list));
</span><span style="color: rgba(0, 128, 128, 1)">10</span> app.use(route.get('/book/:title'<span style="color: rgba(0, 0, 0, 1)">,show));
</span><span style="color: rgba(0, 128, 128, 1)">11</span>
<span style="color: rgba(0, 128, 128, 1)">12</span> <span style="color: rgba(0, 0, 255, 1)">function</span> *<span style="color: rgba(0, 0, 0, 1)">list(){
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">var</span> res =<span style="color: rgba(0, 0, 0, 1)"> yield books.find({});
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.body =<span style="color: rgba(0, 0, 0, 1)"> res;
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">16</span>
<span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 0, 255, 1)">function</span> *<span style="color: rgba(0, 0, 0, 1)">show(){
</span><span style="color: rgba(0, 128, 128, 1)">18</span> title =<span style="color: rgba(0, 0, 0, 1)"> decodeURI(title);
</span><span style="color: rgba(0, 128, 128, 1)">19</span> <span style="color: rgba(0, 0, 255, 1)">var</span> res =<span style="color: rgba(0, 0, 0, 1)"> yield books.find({title:title});
</span><span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.body =<span style="color: rgba(0, 0, 0, 1)"> res;
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 0, 1)">}
</span><span style="color: rgba(0, 128, 128, 1)">22</span>
<span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 255, 1)">if</span>(!module.parent) app.listen(3000);</pre>
</div>
<span class="cnblogs_code_collapse">View Code</span></div>
<p> 我们看到了generator的影子。<br> 4.在上面的express版本中我们使用了自己的数据库中的数据,那么在实际的开发过程中,可能我们会想要调试本地已有的json文件中定义的数据。于是我们同样先起来mongo: </p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> mongod --dbpath ~/work/Node-KOA/koarestapi/data(我们项目目标路径) </pre>
</div>
<p> 然后把数据指向项目中的json文件:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span>mongoimport --db apitest --collection books --file data.json</pre>
</div>
<p> 注意这对json文件中的数据格式稍有要求:</p>
<p> 5.运行实例:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> node --harmony app.js </pre>
</div>
<p> 然后就可以看到我们定义在data.json中的数据了 :</p>
<p><img src="https://images0.cnblogs.com/blog2015/546321/201508/281417420005651.png" alt="" width="218" height="363"></p>
<p> </p>
<p><strong>3.2 更进一步的koa版本的restapi</strong></p>
<p> 同样的,上面只是个简单的例子。使用koa generator-k生成的项目脚手架应该是这样的:</p>
<p> <img src="https://images2015.cnblogs.com/blog/546321/201508/546321-20150829144717578-504203080.png" alt=""></p>
<p> 我们在入口文件app.js中定义基本的依赖和访问入口处理,在controller文件夹中的index.js中定义路由操作,在view中定义页面显示相关。</p>
<p> 非常典型的MVC目录结构。</p>
<p> 更加完整的koa版本的REST项目可以在这里看到:</p>
<h3>四、express还是koa?</h3>
<p> 我们实际动手写过express的项目和koa的项目的话,就会有所体会,相比于koa,express做的事情要多一些,因此他的体积也相对比较大。</p>
<p> 在上面两个例子中我们可以看到,在express版本的例子中我们使用它内置的路由就解决了问题,但是在KOA中我们需要额外的路由中间件,其实更准确的说,koa 内核中没有捆绑任何中间件,连常用的 post body 解析都没有...但这正体现出了koa的优势,koa的体积非常小,表现力更强,它使得中间件的编写变得更加容易。其实可以说,Koa基本上就是一个只有骨架的框架,它具有极强的拓展性,我们可以自己书写可充用和更加符合实际业务场景的中间件,而不用妥协的使用Express自带的中间件。Koa虽然小,但是它通过生成器(generators JavaScript 1.7新引入的,用于解决回调嵌套的方案)减少了异步回调,提高代码的可读性和可维护性,同时改进了错误处理(Express的错误处理方式相当糟糕)。</p>
<p> 同时,Koa是一个采用面向未来的ES6的框架,比如说随处可见的generator函数。</p>
<p> 虽然Koa还不是那么的稳定,但是毫无疑问的它是面向未来的,下一代Nodejs框架。</p>
<p> 那么Koa相比于Express到底优势体现在那些方面呢?总的来说,koa 的先天优势在于 generator,带来的主要好处如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)">更加优雅、简单、安全的中间件机制
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 0, 0, 1)">更加简单、优雅地异常处理
</span><span style="color: rgba(0, 128, 128, 1)">3</span> 更加优雅地异步编程方式</pre>
</div>
<p> 这里有更加官方的说明:</p>
<p> 其实,koa 与 express 是共享底层库的,如果你会使用 express ,那么只要理解 generator 与 koa 框架 api,就可以快速上手。</p>
<p> 如果还没有使用过express那么不如直接开始学习Koa,从这里开始:</p>
<h3>五、参考资料</h3>
<p> <br><br><br><br><br><br>[理解RESTful架构]<br></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p></p>
<p> </p>
<p>&ps-接下来文章预告:</p>
<p> yield语句与Generator函数</p>
<p> KOA实践</p><br><br>
来源:https://www.cnblogs.com/skylar/p/express-koa-restfull-api.html
頁:
[1]