很多人都在关注Deno,我也不例外,毕竟是nodejs之父的又一大作。这篇文章将使用Deno写一个简单的TodoList的RestApi,尝尝鲜。
Deno是什么?
Deno是一个用Rust写的基于 V8 引擎的一个Javascript / Typescript 运行环境。
Deno Features
- Use TypeScript or JavaScript
- ES Modules
- Secure by Default
- Top Level / First Class Await
- De-centralized Packages
- Built In Testing
- Standard Library
- Browser Compatible API
- Modern JS
项目编写
目录结构
- controller
- tasks.ts 定义控制器
- router.ts 定义项目路由
- server.ts 项目主入口,创建http服务器
- tasks.http 测试api
- types.ts 定义接口
由于只是尝尝鲜,数据采用的是静态的,没有连接数据库,就没有写service了。
主要逻辑
Server.ts
import { Application } from 'https://deno.land/x/oak/mod.ts'
import router from './router.ts'
const port = 5000
const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Server running on port ${port}`)
await app.listen({ port })
router.ts
import { Router } from 'https://deno.land/x/oak/mod.ts'
import { getTasks, getTask, updateTask, deleteTask, addTask } from './controller/tasks.ts'
const router = new Router()
router.get('/api/v1/tasks', getTasks)
.get('/api/v1/tasks/:id', getTask)
.post('/api/v1/tasks', addTask)
.put('/api/v1/tasks/:id', updateTask)
.delete('/api/v1/tasks/:id', deleteTask)
export default router
/contraller/tasks.ts
import { v4 } from 'https://deno.land/std/uuid/mod.ts'
import { Task } from '../types.ts'
let tasks: Task[] = [
{
id: "1",
name: "学习Deno",
description: "使用Deno写个小案例",
completed: false
},
{
id: "2",
name: "学习Nodejs",
description: "使用Nodejs写个小案例",
completed: false
},
{
id: "3",
name: "学习Vue",
description: "使用Vue写个小案例",
completed: false
},
{
id: "4",
name: "学习React",
description: "使用React写个小案例",
completed: false
},
{
id: "5",
name: "学习Angular",
description: "使用Angular写个小案例",
completed: false
}
]
/** @desc get all tasks
* @route GET /api/v1/tasks
*/
const getTasks = ({ response }: { response: any }) => {
response.body = {
success: true,
data: tasks
}
}
/** @desc get single task
* @route GET /api/v1/tasks/:id
*/
const getTask = ({ params, response }: { params: {id: string} ,response: any }) => {
const task: Task | undefined = tasks.find(t => t.id === params.id)
if(task) {
response.status = 200
response.body = {
success: true,
data: task
}
} else {
response.status = 404
response.body = {
success: false,
message: 'No task found'
}
}
}
/** @desc add task
* @route POST /api/v1/tasks
*/
const addTask = async ({ request, response }: { request: any,response: any }) => {
const body = await request.body()
if(!request.hasBody){
response.status = 400
response.body = {
success: false,
message: 'No data'
}
} else {
const task: Task = body.value
task.id = v4.generate()
tasks.push(task)
response.status = 201
response.body = {
success: true,
data: task
}
}
}
/** @desc update task by id
* @route PUT /api/v1/tasks/:id
*/
const updateTask = async ({ params, request, response }: { request: any, params: {id: string}, response: any }) => {
const index: number = tasks.findIndex(t => t.id === params.id)
if(index !== -1) {
const body = await request.body()
const updateData: {name?: string, description?: string, completed?: boolean } = body.value
tasks[index] = {...tasks[index], ...updateData}
response.status = 200
response.body = {
success: true,
data: tasks[index]
}
} else {
response.status = 404
response.body = {
success: false,
message: 'No task found'
}
}
}
/** @desc Delete task by id
* @route DELETE /api/v1/tasks/:id
*/
const deleteTask = ({ params, response }: { params: {id: string},response: any }) => {
const index: number = tasks.findIndex(t => t.id === params.id)
if(index !== -1) {
tasks.splice(index,1)
response.status = 200
response.body = {
success: true,
message: 'Task Removed'
}
} else {
response.status = 404
response.body = {
success: false,
message: 'No task found'
}
}
}
export { getTasks, getTask, addTask, updateTask, deleteTask }
可以看到较express、koa的写法差别都不是特别大。
API测试
@host = http://localhost:5000/api/v1
### GET ALl tasks
GET {{host}}/tasks HTTP/1.1
### Get single task
GET {{host}}/tasks/1 HTTP/1.1
### add task
POST {{host}}/tasks HTTP/1.1
Content-Type: application/json
{
"name": "学习Electron",
"description": "使用Electron写个小案例",
"completed": false
}
### update task
PUT {{host}}/tasks/1 HTTP/1.1
Content-Type: application/json
{
"name": "测试",
"description": "测试更新接口",
"completed": true
}
### delete task
DELETE {{host}}/tasks/1 HTTP/1.1
总结
我们不断优化Deno的http服务器的性能。对于'hello world'的例子,DenoHTTP服务器每秒处理约25,000个请求,最大延迟1.3ms。Node服务器每秒处理34,000个请求,最大延迟介于2~300ms之间。
这段话摘自Deno官网。按照官网的说法deno的http性能会比node好很多,不过就目前来说还是很难取代node的。node的生态太丰富了。就我个人的看法来说,我比较喜欢deno的地方在于:
- 内置了TypeScript编译器,写起来很爽啊~~
- 取消掉了package.json管理依赖的模式,不再依靠npm。(npm最让我头痛的一点在于包的下载时不时就会出错,每写一个项目就有一个node_modules)
- 有官方的标准库,可以根据官方的标准库进行开发自己的东西。标准库始终跟着版本走,不会出现第三方库用爱发电,发着发着就不更新了的情况,这点我觉得很好。而且第三方开发的库,始终有些隐患。
- http服务器性能高!!!
总之可以期待一下Deno,后面生态丰富了可以尝试去转Deno。
欢迎来一起交流👏。