30分钟用Node.js构建一个API服务器的步骤详解


Posted in Javascript onMay 24, 2019

Node.js 对初学者来说可能是令人望而却步的,其灵活的结构和缺乏严格的规范使它看起来很复杂。

本教程是 Node.js,Express 框架和 MongoDB 的快速指南,重点介绍基本的 REST 路由和基本的数据库交互。你将构建一个简单的 API 框架模版,然后可以将其用作任何应用。

本教程适用于:你应该对 REST API 和 CRUD 操作有基本的了解,还有基本的 JavaScript 知识。我用的是 ES6(主要是箭头函数),但并不是很复杂。

在本教程中,我们将为创建一个网络笔记应用的后端骨架 —— 类似于Google Keep,能够执行所有的四个CRUD操作:创建、读取、更新和删除。

配置

如果你没有安装Node,请参阅此处。

创建一个新目录,运行 npm init,然后按照提示操作,把你的应用程序命名为“notable”(或者你可能喜欢的其他名字)。

npm init

一旦完成,在你的目录中会有一个 package.json 文件。你可以开始安装项目所需的依赖项了。

我们将使用 Express 作为自己的框架,MongoDB 作为数据库,还有一个名为 body-parser 的包来帮助处理 JSON 请求。

npm install --save express mongodb@2.2.16 body-parser

我还强烈建议将 Nodemon 安装为 dev 依赖项。这是一个非常简单的小包,可在文件被更改时自动重启服务器。

如果你运行:

npm install --save-dev nodemon

然后将以下脚本添加到 package.json

// package.json
 "scripts": {
  "dev": "nodemon server.js"
 },

完整的 package.json 应如下所示:

// package.json
{
 "name": "notable",
 "version": "1.0.0",
 "description": "",
 "main": "server.js",
 "scripts": {
  "dev": "nodemon server.js"
 },
 "author": "",
 "license": "ISC",
 "dependencies": {
  "body-parser": "^1.15.2",
  "express": "^4.14.0",
  "mongodb": "^2.2.16"
 },
 "devDependencies": {
  "nodemon": "^1.11.0"
 }
}

现在,你可以创建 server.js 文件并构建 API 了。

我们的服务器

首先导入 server.js 中的所有依赖项。

// server.js
const express    = require('express');
const MongoClient  = require('mongodb').MongoClient;
const bodyParser   = require('body-parser');
const app      = express();

我们将使用 MongoClient 与数据库进行交互。还会将应用初始化为 Express 框架的实例。

最后一件事就是告诉你的程序开始监听请求。

你可以指定一个端口,并像这样开始监听:

// server.js
const port = 8000;
app.listen(port, () => {
 console.log('We are live on ' + port);
});

现在,如果你运行 npm run dev(或 node server.js,如果你没有安装 Nodemon 的话),应该在终端中看到“We are live on port 8000”的提示。

你的服务器已经启动了。但它现在还什么也做不了。

接下来让我们解决这个问题。

CRUD 路由

对于本例,你要构建4条路由; 创建笔记,阅读笔记,更新笔记和删除笔记。

这将使你了解如何使用 Node 构建几乎所有的基本路由。

但是,要测试你的API,还需要模仿客户端发出请求。为此,我们将使用名为 Postman 的优秀应用。它允许你使用自定义的头和参数进行简单的 HTTP 请求。

安装Postman,让我们开始设置路由。

项目结构

大多数 Node.js 教程(以及许多真实的案例)都将所有路由放在一个很大的 routes.js 文件中。这让我有点不舒服。相比之下,将文件拆到为单独的文件夹可以提高可读性,并使大型应用更易于管理。

虽然我们现在做的不是大型应用,但仍然可以这样做。创建以下目录:一个 app 文件夹,里面有一个routes文件夹,routes 里面有 index.jsnote_routes.js 文件。

mkdir app
cd app
mkdir routes
cd routes
touch index.js
touch note_routes.js

对于你的简单小程序来说,这些目录可能看起来有些过分,但从一开始就做好总是有意义的。

你的第一个路由

让我们从 CRUD 中的 C 开始。你将会如何创建一个笔记?

那么,在你开始之前,必须先要打好基础。在Express中,路由包含在一个函数中,该函数将 Express 实例和数据库作为参数。

像这样:

// routes/note_routes.js
module.exports = function(app, db) {
};

然后,你可以通过 index.js 导出此函数:

// routes/index.js
const noteRoutes = require('./note_routes');
module.exports = function(app, db) {
 noteRoutes(app, db);
 // Other route groups could go here, in the future
};

然后导入它以便在 server.js 中使用:

// server.js
const express    = require('express');
const MongoClient  = require('mongodb').MongoClient;
const bodyParser   = require('body-parser');
const app      = express();
const port = 8000;
require('./app/routes')(app, {});
app.listen(port, () => {
 console.log('We are live on ' + port);
});

请注意,由于还没有设置数据库,因此只需传入一个空对象。

好的,现在你可以制作自己的 CREATE 路由了。

语法很简单:

// note_routes.js
module.exports = function(app, db) {
 app.post('/notes', (req, res) => {
  // You'll create your note here.
  res.send('Hello')
 });
};

当应用程序收到对 '/ notes' 路径的 post 请求时,它将执行回调内的代码 —— request 对象(包含请求的参数或JSON)和 response 对象。

你可以使用 Postman 将 POST 请求发送到 localhost:8000/notes 来测试。

30分钟用Node.js构建一个API服务器的步骤详解

你应该得到回复:'Hello'。

太好了!你创建了第一个真正的路由。

下一步是在你的请求中添加一些参数并在 API 中处理它们,最后添加到你的数据库中。

请求参数

在 Postman 中,在选择 x-www-form-urlencoded 单选按钮后,转到 Body 选项卡并添加一些键值对。

这会将编码后的表单数据添加到你的请求中,你可以使用 API ​​处理该请求。

30分钟用Node.js构建一个API服务器的步骤详解

你可以去尝试更多的设置项。

现在在你的 note_routes.js 中,让我们输出 body 的内容。

// note_routes.js
module.exports = function(app, db) {
 app.post('/notes', (req, res) => {
  console.log(req.body)
  res.send('Hello')
 });
};

用 Postman 发送请求,你会看到……undefined。

不幸的是,Express 无法自行处理 URL 编码的表单。虽然你确实安装了这个 body-parser 包......

// server.
const express    = require('express');
const MongoClient  = require('mongodb').MongoClient;
const bodyParser   = require('body-parser');
const app      = express();
const port = 8000;
app.use(bodyParser.urlencoded({ extended: true }));
require('./app/routes')(app, {});
app.listen(port, () => {
 console.log('We are live on ' + port);
});

Now you should see the body as an object in the terminal.

现在你应该将 body 视为终端中的对象。

{ title: 'My Note Title', body: 'What a great note.' }

第一个路由的最后一步:设置数据库,然后添加数据。

最简单方法是通过mLab 设置 Mongo 数据库的:它是最小的而且是免费的,设置的速度非常快。

创建帐户和 MongoDB 部署后,将用户的用户名和密码添加到数据库:

30分钟用Node.js构建一个API服务器的步骤详解

然后复制这里第二个 URL:

30分钟用Node.js构建一个API服务器的步骤详解

在项目根目录的目录配置中,创建一个db.js文件。

mkdir config 
cd config
touch db.js

在里面,添加刚才的URL:

module.exports = {
 url : YOUR URL HERE
};

别忘了把你的用户名和密码(来自数据库用户的密码,而不是你的 mLab 帐户)添加到URL中。 (如果你要将此项目提交到 Github 上,请确保包含 .gitignore 文件 像这样,,不要与任何人分享你的密码。)

现在在你的 server.js 中,可以用 MongoClient 连接到数据库了,使用它来包装你的应用程序设置:

// server.js
const express    = require('express');
const MongoClient  = require('mongodb').MongoClient;
const bodyParser   = require('body-parser');
const db       = require('./config/db');
const app      = express();
const port = 8000;
app.use(bodyParser.urlencoded({ extended: true }));
MongoClient.connect(db.url, (err, database) => {
 if (err) return console.log(err)
 require('./app/routes')(app, database);
 app.listen(port, () => {
  console.log('We are live on ' + port);
 });        
})

如果你用的是最新版本的 MongoDB(3.0+),请将其修改为:

// server.js
const express    = require('express');
const MongoClient  = require('mongodb').MongoClient;
const bodyParser   = require('body-parser');
const db       = require('./config/db');
const app      = express();
const port = 8000;
app.use(bodyParser.urlencoded({ extended: true }));
MongoClient.connect(db.url, (err, database) => {
 if (err) return console.log(err)
           
 // Make sure you add the database name and not the collection name
 const database = database.db("note-api")
 require('./app/routes')(app, database);
 app.listen(port, () => {
  console.log('We are live on ' + port);
 });        
})

这是你的基础架构的最后一个设置!

添加到你的数据库

MongoDB将数据存储在 collections 中。在你的项目中,你希望将笔记存储在一个名为 notes 的 collection 中。

由于将数据库作为路径中的 db 参数传入,因此可以像这样访问它:

db.collection('notes')

创建笔记就像在集合上调用 insert 一样简单:

const note = { text: req.body.body, title: req.body.title}
 db.collection('notes').insert(note, (err, results) => {
}

插入完成后(或由于某种原因失败),要么返回错误或反回新创建的笔记对象。这是完整的 note_routes.js 代码:

// note_routes.js
module.exports = function(app, db) {
 const collection = 
 app.post('/notes', (req, res) => {
  const note = { text: req.body.body, title: req.body.title };
  db.collection('notes').insert(note, (err, result) => {
   if (err) { 
    res.send({ 'error': 'An error has occurred' }); 
   } else {
    res.send(result.ops[0]);
   }
  });
 });
};

试试看!使用 Postman 发送 x-www-form-urlencoded POST 请求,在 Body 选项卡下设置 titlebody

响应应如下所示:

30分钟用Node.js构建一个API服务器的步骤详解

如果你登录mLab,你还应该能够在数据库中看到创建的笔记。

READ 路由

现在可以稍微加快步伐。

假设你希望通过导航到 localhost:8000/notes/{id} 来获取刚创建的笔记。这是链接应该是localhost:8000/notes/585182bd42ac5b07a9755ea3。(如果你没有得到其中笔记的 ID,可以通过检查 mLab 或创建一个新的笔记)。

以下是 note_routes.js 中的内容:

// note_routes.js
module.exports = function(app, db) {
 app.get('/notes/:id', (req, res) => {
  
 });
 app.post('/notes', (req, res) => {
  const note = { text: req.body.body, title: req.body.title };
  db.collection('notes').insert(note, (err, result) => {
   if (err) { 
    res.send({ 'error': 'An error has occurred' }); 
   } else {
    res.send(result.ops[0]);
   }
  });
 });
};

就像以前一样,你将在数据库 collection 中调用一个方法。在这里,它被恰当地命名为 findOne。

// note_routes.js
module.exports = function(app, db) {
 app.get('/notes/:id', (req, res) => {
  const details = { '_id': <ID GOES HERE> };
  db.collection('notes').findOne(details, (err, item) => {
   if (err) {
    res.send({'error':'An error has occurred'});
   } else {
    res.send(item);
   }
  });
 });
app.post('/notes', (req, res) => {
  const note = { text: req.body.body, title: req.body.title };
  db.collection('notes').insert(note, (err, result) => {
   if (err) { 
    res.send({ 'error': 'An error has occurred' }); 
   } else {
    res.send(result.ops[0]);
   }
  });
 });
};

你可以通过 req.params.id 从 URL 参数中获取 id。但是,如果你试图将字符串插入上面的 <ID GOES HERE> 位置,它将无法正常工作。

MongoDB 不仅要求 ID 为字符串,还要求 ID 是一个对象,它们被之为 ObjectID。

别担心,这很容易解决。这是完整的代码:

// note_routes.js
var ObjectID = require('mongodb').ObjectID;
module.exports = function(app, db) {
 app.get('/notes/:id', (req, res) => {
  const id = req.params.id;
  const details = { '_id': new ObjectID(id) };
  db.collection('notes').findOne(details, (err, item) => {
   if (err) {
    res.send({'error':'An error has occurred'});
   } else {
    res.send(item);
   } 
  });
 });
app.post('/notes', (req, res) => {
  const note = { text: req.body.body, title: req.body.title };
  db.collection('notes').insert(note, (err, result) => {
   if (err) { 
    res.send({ 'error': 'An error has occurred' }); 
   } else {
    res.send(result.ops[0]);
   }
  });
 });
};

尝试使用一个笔记 ID,它应如下所示:

30分钟用Node.js构建一个API服务器的步骤详解

DELETE 路由

实际上删除对象与查找对象几乎相同。你只需用 remove 函数替换 findOne 即可。这是完整的代码:

// note_routes.js
// ...
 app.delete('/notes/:id', (req, res) => {
  const id = req.params.id;
  const details = { '_id': new ObjectID(id) };
  db.collection('notes').remove(details, (err, item) => {
   if (err) {
    res.send({'error':'An error has occurred'});
   } else {
    res.send('Note ' + id + ' deleted!');
   } 
  });
 });
// ...

UPDATE 路由

最后一个! PUT 方法基本上是 READ 和 CREATE 的混合体。你找到该对象,然后更新它。如果刚才你删除了数据库中唯一的笔记,那就再创建一个!

代码:

// note_routes.js
// ...
 app.put('/notes/:id', (req, res) => {
  const id = req.params.id;
  const details = { '_id': new ObjectID(id) };
  const note = { text: req.body.body, title: req.body.title };
  db.collection('notes').update(details, note, (err, result) => {
   if (err) {
     res.send({'error':'An error has occurred'});
   } else {
     res.send(note);
   } 
  });
 });
// ...

现在你可以更新任何笔记,如下所示:

30分钟用Node.js构建一个API服务器的步骤详解

请注意这些代码还不完美 —— 比如你没有提供正文或标题,PUT 请求将会使数据库中的笔记上的那些字段无效。

API 完成

就这么简单!你完成了可以进行 CRUD 操作的 Node API。

本教程的目的是让你熟悉 Express、Node 和 MongoDB —— 你可以用简单的程序作为进军更复杂项目的跳板。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 学习 - 提高篇
Feb 02 Javascript
学习ExtJS Panel常用方法
Oct 07 Javascript
javascript 年月日联动实现核心代码
Dec 21 Javascript
js替换字符串的所有示例代码
Jul 23 Javascript
node.js不得不说的12点内容
Jul 14 Javascript
js编写当天简单日历效果【实现代码】
May 03 Javascript
原生js实现旋转木马轮播图效果
Feb 27 Javascript
jQuery实现字体颜色渐变效果的方法
Mar 29 jQuery
使用vue构建移动应用实战代码
Aug 02 Javascript
利用jqprint插件打印页面内容的实现方法
Jan 09 Javascript
JavaScript设计模式之代理模式简单实例教程
Jul 03 Javascript
Electron-vue开发的客户端支付收款工具的实现
May 24 #Javascript
JS实现判断数组是否包含某个元素示例
May 24 #Javascript
JS实现查找数组中对象的属性值是否存在示例
May 24 #Javascript
jQuery中使用validate插件校验表单功能
May 24 #jQuery
echarts多条折线图动态分层的实现方法
May 24 #Javascript
Echarts动态加载多条折线图的实现代码
May 24 #Javascript
JavaScript遍历查找数组中最大值与最小值的方法示例
May 24 #Javascript
You might like
PHP 变量类型的强制转换
2009/10/23 PHP
PHP数组传递是值传递而非引用传递概念纠正
2013/01/31 PHP
php smarty模板引擎的6个小技巧
2014/04/24 PHP
destoon供应信息title调用出公司名称的方法
2014/08/22 PHP
php通过ksort()函数给关联数组按照键排序的方法
2015/03/18 PHP
JavaScript this 深入理解
2009/07/30 Javascript
jquery tablesorter.js 支持中文表格排序改进
2009/12/09 Javascript
基于Jquery的实现回车键Enter切换焦点
2010/09/14 Javascript
javascript闭包的高级使用方法实例
2013/07/04 Javascript
jQuery插件slick实现响应式移动端幻灯片图片切换特效
2015/04/12 Javascript
js实现文字滚动效果
2016/03/03 Javascript
详解js中==与===的区别
2017/01/08 Javascript
详解如何实现一个简单的Node.js脚手架
2017/12/04 Javascript
JS和Canvas实现图片的预览压缩和上传功能
2018/03/30 Javascript
JS实现的DOM插入节点操作示例
2018/04/04 Javascript
node.js中TCP Socket多进程间的消息推送示例详解
2018/07/10 Javascript
Vue CLI3搭建的项目中路径相关问题的解决
2018/09/17 Javascript
JS实现求5的阶乘示例
2019/01/21 Javascript
vue强制刷新组件的方法示例
2019/02/28 Javascript
详解一次Vue低版本安卓白屏问题的解决过程
2019/05/30 Javascript
微信小程序自定义navigationBar顶部导航栏适配所有机型(附完整案例)
2020/04/26 Javascript
[02:26]DOTA2英雄米拉娜基础教程
2013/11/25 DOTA
python中使用百度音乐搜索的api下载指定歌曲的lrc歌词
2014/07/18 Python
Python的类实例属性访问规则探讨
2015/01/30 Python
搞定这套Python爬虫面试题(面试会so easy)
2019/04/03 Python
Python生成rsa密钥对操作示例
2019/04/26 Python
在python中画正态分布图像的实例
2019/07/08 Python
Python函数的定义方式与函数参数问题实例分析
2019/12/26 Python
WWE美国职业摔角官方商店:WWE Shop
2018/11/15 全球购物
应届中专生自荐书范文
2014/02/13 职场文书
跑操口号
2014/06/12 职场文书
区域销售主管岗位职责
2014/06/15 职场文书
校园开放日新闻稿
2015/07/17 职场文书
win10安装配置nginx的过程
2021/03/31 Servers
ORACLE数据库对long类型字段进行模糊匹配的解决思路
2021/04/07 Oracle
Win10 最新稳定版本 21H2开始推送
2022/04/19 数码科技