作者:Flavio Copes翻译:疯狂的技术宅
原文:https://www.freecodecamp.org/...
未经允许严禁转载
我每周都会探索一些新的项目,但很少会有像 Deno 这样吸引我的。
在本文中,我会让你快速了解 Deno,并把它与 Node.js 进行比较,以此构建你的第一个 REST API。
什么是Deno?
Deno 就像 Node,但是在很多方面都得到了深入的改善。先从 Deno 功能列表开始:
- 它基于 JavaScript 语言的现代功能
- 它有全面的标准库
- 它以 TypeScript 为核心,以许多不同的方式带来了巨大的优势,包括一流的 TypeScript 支持(你不必单独编译 TypeScript,它由 Deno 自动完成)
- 它包含 ES 模块
- 没有包管理器
- 它有一流的
await
- 内置测试功能
- 它尽可能地与浏览器保持兼容,例如提供内置的
fetch
和全局window
对象
我们将在本指南中探索所有这些功能。
在你开始使用 Deno 并了解了其功能之后,Node.js 看起来就像是“旧的”东西。
特别是因为 Node.js API 是基于回调的,它是在 promise 和 async/await之前编写的。 Node 中没有可用于修改的余地,这种修改的代价将会是巨大的。所以我们只能用回调或大量的 API 调用。
Node.js 非常棒,并将继续成为 JavaScript 世界中事实上的标准。但是我想我们会逐渐看到 Deno 由于其一流的 TypeScript 支持和现代标准库而越来越被广泛的采用。
由于没有向后兼容性的报复,所以 Deno 可以用现代技术编写所有的东西。当然我们无法保证十年之内在 Deno 身上也会发生同样的事情,并且会出现一项新技术,但这是目前的现实。
为什么是 Deno?为什么是现在?
大约2年前,Node.js 的原始创建者 Ryan Dahl 在 JSConf EU 上宣布了 Deno(油管上的演讲视频),这非常有趣,如果你经常用 Node.js 和 JavaScript,那么它是必看的。
每个项目经理都必须做出决定。 Ryan 对 Node 中的一些早期决定感到遗憾。此外,技术也在不断发展,如今的 JavaScript 与 2009 年 Node 创立时的语言已经完全不同。比如现代的 ES6/2016/2017 功能等。
所以他开始了一个新项目,用来创建第二波基于 JavaScript 的服务器端程序。
我现在而不是两年前写本文的原因是,技术需要大量时间才能成熟。我们终于达到了 Deno 1.0(1.0 在2020年5月13日发布),这是 Deno 正式宣布稳定的第一版。
这似乎只是一个数字,但 1.0 表示直到 Deno 2.0 才会有重大突破。当你采用一种新技术时,这很重要——你不想学习某些东西,因为它改变得太快。
你应该学习Deno吗?
这是一个大问题。
学习诸如 Deno 之类的新东西需要很大的努力。我的建议是,如果你现在开始使用服务器端 JS,并且还不了解 Node,并且从未编写过任何 TypeScript 代码,那么就从 Node 开始。没有人因为选择 Node.js 而被解雇。
但是,如果你喜欢 TypeScript,想要在任何地方使用 await
,但不想依赖项目中庞大的 npm 包,那么 Deno 可能就是你想要的。
它会取代 Node.js 吗?
答案是否定的。Node.js 是一项庞大的、完善的、获得了良好支持的技术,它将会持续数十年。
一流的TypeScript支持
Deno 用 Rust 和 TypeScript 编写,这两种语言今天正在迅速发展。
特别是使用 TypeScript 意味着即使我们选择用纯 JavaScript编写代码,也可以获得 TypeScript 的很多好处。
使用 Deno 运行 TypeScript 代码不需要编译步骤——Deno 会自动为你执行这一步骤。
你不会被迫使用 TypeScript 编写代码,但是 Deno 的核心是用 TypeScript 编写的这一事实是明显的。
首先越来越多的 JavaScript 程序员开始喜欢 TypeScript。
其次,你使用的工具可以推断出许多有关用 TypeScript 编写的软件的信息,例如 Deno。
这意味着,当我们用 VS Code 进行编码时(由于二者都是在 MicroSoft 上开发的,因此与 TypeScript 紧密集成),可以在编写代码时获得类型检查和高级 IntelliSense 功能。换句话说,编辑器能够以非常有用的方式帮助我们。
与 Node.js 的异同
由于 Deno 基本上是 Node.js 的替代品,所以直接对两者比较非常有用。
相似之处:
- 两者都是基于 V8 Chromium Engine 开发的
- 两者都非常适合用 JavaScript 开发服务器端
差异:
- Node 用 C++ 和 JavaScript 编写。 Deno 用 Rust 和 TypeScript 编写。
- Node 有一个名为
npm
的官方包管理器。 Deno 没有,而是让你从 URL 导入任何 ES 模块。 - Node 使用 CommonJS 语法导入 pacakges。 Deno 使用官方的 ES 模块。
- Deno 在其所有 API 和标准库中使用现代 ECMAScript 功能,而 Node.js 使用基于回调的标准库,并且没有计划对其进行升级。
- Deno 通过权限提供了一个沙箱安全层。程序只能访问由用户设置为可执行文件的权限作为标志。 Node.js 程序可以访问用户有权访问的任何内容。
- Deno 长期以来一直在考虑将程序编译成可执行文件的可能性,而这种可执行文件可以在没有外部依赖项的情况下运行,就像 Go 一样,不过现在还没有正式提上日程。这将改变游戏规则。
没有包管理器
没有包管理器并且必须依靠 URL 来承载和导入包有利有弊。我真的很喜欢 pros:它非常灵活,我们可以创建软件包而无需将其发布到 npm 这样的存储库中。
我认为会有某种包管理器出现,但是还没有官方的消息。
Deno 网站为第三方软件包提供代码托管(并通过 URL 分发):https://deno.land/x/
安装 Deno
聊的够多了!下面开始安装 Deno。
在 Mac 上最简单的方法是用 Homebrew:
brew install deno
一旦完成,你将可以访问 deno
命令。下面是你可以用 deno --help
获得的帮助:
flavio@mbp~> deno --help
deno 0.42.0
A secure JavaScript and TypeScript runtime
Docs: https://deno.land/std/manual.md
Modules: https://deno.land/std/ https://deno.land/x/
Bugs: https://github.com/denoland/deno/issues
To start the REPL, supply no arguments:
deno
To execute a script:
deno run https://deno.land/std/examples/welcome.ts
deno https://deno.land/std/examples/welcome.ts
To evaluate code in the shell:
deno eval "console.log(30933 + 404)"
Run 'deno help run' for 'run'-specific flags.
USAGE:
deno [OPTIONS] [SUBCOMMAND]
OPTIONS:
-h, --help
Prints help information
-L, --log-level <log-level>
Set log level [possible values: debug, info]
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-V, --version
Prints version information
SUBCOMMANDS:
bundle Bundle module and dependencies into single file
cache Cache the dependencies
completions Generate shell completions
doc Show documentation for a module
eval Eval script
fmt Format source files
help Prints this message or the help of the given subcommand(s)
info Show info about cache or info related to source file
install Install script as an executable
repl Read Eval Print Loop
run Run a program given a filename or url to the module
test Run tests
types Print runtime TypeScript declarations
upgrade Upgrade deno executable to newest version
ENVIRONMENT VARIABLES:
DENO_DIR Set deno's base directory (defaults to $HOME/.deno)
DENO_INSTALL_ROOT Set deno install's output directory
(defaults to $HOME/.deno/bin)
NO_COLOR Set to disable color
HTTP_PROXY Proxy address for HTTP requests
(module downloads, fetch)
HTTPS_PROXY Same but for HTTPS
Deno 命令
请注意帮助中的 SUBCOMMANDS
部分,其中列出了我们可以运行的所有命令。都有哪些子命令呢?
-
bundle
把模块和项目的依赖关系打包到单个文件中 -
cache
缓存依赖项 -
completions
生成 shell 补全 -
doc
显示模块的文档 -
eval
用来评估一段代码,例如deno eval "console.log(1 + 2)"
-
fmt
内置的代码格式化程序(类似于 Go 中的gofmt
) -
help
打印此消息或给定子命令的帮助 -
info
显示有关缓存的信息或与源文件有关的信息 -
install
把脚本作为可执行文件进行安装 -
repl
读取评估打印循环(默认) -
run
运行为模块指定文件名或 URL 的程序 -
test
运行测试 -
types
打印运行时 TypeScript 声明 -
upgrade
upgradedeno
to the newest version -
upgrade
升级到最新版本的deno
可以运行 deno help
来获取命令的特定其他说明,例如 deno run --help
。
就像帮助所说的那样,我们可以用这个命令使 deno 来启动REPL(Read-Execute-Print-Loop),而无需任何其他操作。
这与运行 deno repl
相同。
这个命令的一种更常见的使用方法是执行包含在 TypeScript 文件中的 Deno 程序。
你可以同时运行 TypeScript(.ts
)文件与 JavaScript(.js
)文件。
如果你不熟悉 TypeScript,请不要担心:尽管 Deno 是用 TypeScript 编写的,但是你也可以用 JavaScript 编写“客户端”程序。
第一个 Deno 程序
让我们运行第一个 Deno 应用程序。
我感到非常惊奇的是,甚至不需要写一行代码代码——你可以从任何 URL 运行命令。
Deno下载程序,进行编译,然后运行:
当然,从互联网上运行任意代码不是一种建议做法。不过我们是从 Deno 官方网站上运行它的,另外,Deno 还有一个沙箱,可以阻止程序执行你不希望做的任何事情。稍后再详细介绍。
这个程序非常简单,只需调用 console.log()
即可:
console.log('Welcome to Deno ?')
如果用浏览器打开 URL https://deno.land/std/example... ,则会看到以下页面:
奇怪吧?你可能希望拿到 TypeScript 文件,但是却得到了一个网页。原因是 Deno 网站的 Web 服务器知道你正在使用浏览器,并为你提供了更加用户友好的页面。
例如,用 wget
下载相同的UR,它要求使用 text/plain
版本而不是 text/html
:
如果你想再次运行该程序,那么现在它已由 Deno 缓存,不需要再次下载:
你可以使用 `--reload
标志来强制重新加载原始源:
deno run
有许多没有在 deno --help
中列出的选项。你需要运行 deno run --help
来显示它们:
flavio@mbp~> deno run --help
deno-run
Run a program given a filename or url to the module.
By default all programs are run in sandbox without access to disk, network or
ability to spawn subprocesses.
deno run https://deno.land/std/examples/welcome.ts
Grant all permissions:
deno run -A https://deno.land/std/http/file_server.ts
Grant permission to read from disk and listen to network:
deno run --allow-read --allow-net https://deno.land/std/http/file_server.ts
Grant permission to read whitelisted files from disk:
deno run --allow-read=/etc https://deno.land/std/http/file_server.ts
USAGE:
deno run [OPTIONS] <SCRIPT_ARG>...
OPTIONS:
-A, --allow-all
Allow all permissions
--allow-env
Allow environment access
--allow-hrtime
Allow high resolution time measurement
--allow-net=<allow-net>
Allow network access
--allow-plugin
Allow loading plugins
--allow-read=<allow-read>
Allow file system read access
--allow-run
Allow running subprocesses
--allow-write=<allow-write>
Allow file system write access
--cached-only
Require that remote dependencies are already cached
--cert <FILE>
Load certificate authority from PEM encoded file
-c, --config <FILE>
Load tsconfig.json configuration file
-h, --help
Prints help information
--importmap <FILE>
UNSTABLE:
Load import map file
Docs: https://deno.land/std/manual.md#import-maps
Specification: https://wicg.github.io/import-maps/
Examples: https://github.com/WICG/import-maps#the-import-map
--inspect=<HOST:PORT>
activate inspector on host:port (default: 127.0.0.1:9229)
--inspect-brk=<HOST:PORT>
activate inspector on host:port and break at start of user script
--lock <FILE>
Check the specified lock file
--lock-write
Write lock file. Use with --lock.
-L, --log-level <log-level>
Set log level [possible values: debug, info]
--no-remote
Do not resolve remote modules
-q, --quiet
Suppress diagnostic output
By default, subcommands print human-readable diagnostic messages to stderr.
If the flag is set, restrict these messages to errors.
-r, --reload=<CACHE_BLACKLIST>
Reload source code cache (recompile TypeScript)
--reload
Reload everything
--reload=https://deno.land/std
Reload only standard modules
--reload=https://deno.land/std/fs/utils.ts,https://deno.land/std/fmt/colors.ts
Reloads specific modules
--seed <NUMBER>
Seed Math.random()
--unstable
Enable unstable APIs
--v8-flags=<v8-flags>
Set V8 command line options. For help: --v8-flags=--help
ARGS:
<SCRIPT_ARG>...
script args
Deno 代码示例
除了上面运行的示例外,Deno 网站还提供了一些其他例子,你可以在这找到它们:https://deno.land/std/examples/。
在撰写本文时,我们可以找到:
-
cat.ts
: 打印作为参数提供的文件列表的内容 -
catj.ts
: 打印作为参数提供的文件列表的内容 -
chat/
: 一个聊天程序的实现 -
colors.ts
: 一个例子 -
curl.ts
:curl
的简单实现,可打印作为参数输入的 URL 的内容 -
echo_server.ts
: 一个 TCP 回显服务器 -
gist.ts
:一个将文件发布到 gist.github.com 的程序 -
test.ts
:测试的例子 -
welcome.ts
:一个简单的 console.log 语句(我们在上面运行的第一个程序) -
xeval.ts
允许你为收到的任何标准输入行运行任何 TypeScript 代码。 曾经是deno xeval
命令,但此后已从官方命令中删除。
你自己的第一个 Deno 程序
让我们写一些代码。
你使用 deno run https://deno.land/std/examples/welcome.ts
运行的 Deno 程序是别人写的,所以你对 Deno 代码的样子一无所知。
我们将从 Deno 官方网站上列出的默认示例开始:
import { serve } from 'https://deno.land/std/http/server.ts'
const s = serve({ port: 8000 })
console.log('http://localhost:8000/')
for await (const req of s) {
req.respond({ body: 'Hello World\n' })
}
该代码从 http/server
模块导入 serve
函数。看到没?我们不必事先安装它,也不会像 Node 模块那样将其存储在本地计算机上。这是 Deno 安装如此之快的原因之一。
从 https://deno.land/std/http/se... 会导入模块的最新版本。你可以使用 @VERSION
导入特定版本,如下所示:
import { serve } from 'https://deno.land/std@v0.42.0/http/server.ts'
在这个文件中,serve
函数的定义如下:
/**
* Create a HTTP server
*
* import { serve } from "https://deno.land/std/http/server.ts";
* const body = "Hello World\n";
* const s = serve({ port: 8000 });
* for await (const req of s) {
* req.respond({ body });
* }
*/
export function serve(addr: string | HTTPOptions): Server {
if (typeof addr === 'string') {
const [hostname, port] = addr.split(':')
addr = { hostname, port: Number(port) }
}
const listener = listen(addr)
return new Server(listener)
}
我们继续实例化一个调用 serve()
函数的服务器,该服务器传递带有 port
属性的对象。
然后,我们运行这个循环来响应来自服务器的每个请求。
for await (const req of s) {
req.respond({ body: 'Hello World\n' })
}
请注意,由于 Deno 实现了 top-level await,因此无需使用 await
关键字即可将其包装到 async
函数中。
让我们在本地运行该程序。假设你用的是 VS Code,不过你可以使用任何喜欢的编辑器。
我建议从 justjavac
安装 Deno 扩展(我尝试时有另一个名称相同,但已弃用的扩展——将来可能会消失)
该扩展将提供一些能够给 VS Code 带来好处的实用工具,帮助你编写程序。
下面在文件夹中创建一个 app.ts
文件,并粘贴上面的代码:
然后用 deno run app.ts
运行:
Deno 首先下载我们导入的依赖项,然后再下载所需的所有依赖项。
https://deno.land/std/http/se... 文件本身有多个依赖项:
import { encode } from '../encoding/utf8.ts'
import { BufReader, BufWriter } from '../io/bufio.ts'
import { assert } from '../testing/asserts.ts'
import { deferred, Deferred, MuxAsyncIterator } from '../async/mod.ts'
import {
bodyReader,
chunkedBodyReader,
emptyReader,
writeResponse,
readRequest,
} from './_io.ts'
import Listener = Deno.Listener
import Conn = Deno.Conn
import Reader = Deno.Reader
并且这些都是自动导入的。
尽管最后我们遇到了一个问题:
怎么回事?我们遇到了一个权限被拒绝的问题。
接下来要谈谈沙箱。
Deno 沙箱
之前我曾经提到过,Deno 的沙箱可以防止程序执行你不希望做的任何事情。
这是什么意思?
Ryan 在 Deno 简介演讲中提到过,有时你想在 Web 浏览器之外运行 JavaScript 程序,但又不想让它访问系统上任何内容,或使用网络与外界对话。
没有什么方法能够阻止 Node.js 应用获取你系统上的 SSH 密钥或任何其他的东西,并将其发送到服务器。这就是为什么我们通常只从受信任的源安装 Node 软件包的原因。但是,我们怎么知道自己使用的项目是否遭到黑客入侵,而其他人是否被黑客入侵呢?
Deno 尝试复制与浏览相同的权限模型。除非你明确允许,否则在浏览器中运行的 JavaScript 不会在你的系统上做任何令人作呕的事情。
回到 Deno,如果一个程序想要像以前那样访问网络,那么我们需要给它权限。
可以通过在运行命令时传递一个标志来实现,在本例中是 --allow-net
:
deno run --allow-net app.ts
现在该程序可以在端口 8000 上运行 HTTP 服务器了:
有很多允许 Deno 解锁其他功能的标志:
-
--allow-env
允许环境访问 -
--allow-hrtime
允许高精度的时间测量 -
--allow-net =
允许网络访问 -
--allow-plugin
允许加载插件 -
--allow-read =
允许文件系统读访问 -
--allow-run
允许运行子进程 -
--allow-write =
允许文件系统写访问 -
--allow-all
允许所有权限(与-A
相同)
net
、 read
和 write
的权限可以是细粒度的。例如你可以用 --allow-read=/dev
来允许从特定目录中读取
格式化代码
我喜欢 Go 语言的一个原因是 Go 编译器附带的 gofmt
命令。所有的 Go 代码看起来都一样。每个人都在用 gofmt
。
JavaScript 程序员习惯于运行 Prettier,deno fmt
实际上是在后台运行的。
假设你有一个格式很乱的文件,如下所示:
运行 deno fmt app.ts
,它会自动被正确的格式化,还会在缺少分号的地方自动添加:
标准库
尽管这个项目还很年轻,但 Deno 的标准库仍然很庞大。
其中包括:
-
archive
: tar 存档工具 -
async
async utilties -
async
:异步工具 -
bytes
:用来操作字节片段的辅助 -
datetime
: 日期/时间解析 -
encoding
:各种格式的编码/解码功能 -
flags
: 解析命令行标志 -
fmt
: 格式化和打印 -
fs
:文件系统 API -
hash
:加密库 -
http
: HTTP服务器 -
io
: I/O 库 -
log
: 日志实用工具 -
mime
:支持 multipart 数据 -
node
: Node.js 兼容性层 -
path
:路径操作 -
ws
: websockets
另一个Deno示例
让我们查看另一个 Deno 应用示例:cat
:
const filenames = Deno.args
for (const filename of filenames) {
const file = await Deno.open(filename)
await Deno.copy(file, Deno.stdout)
file.close()
}
这会将 Deno.args
的内容赋值给 filenames
变量,这一变量是包含发送到命令的所有参数的变量。
我们遍历它们,对于每一个文件名我们都用 Deno.open()
打开文件,然后使用 Deno.copy()
将文件的内容打印到 Deno.stdout
。最后关闭文件。
如果你这样执行:
deno run https://deno.land/std/examples/cat.ts
那么该程序会被下载并编译,但没有任何反应,因为我们没有指定任何参数。
现在试试
deno run https://deno.land/std/examples/cat.ts app.ts
假设你在同一文件夹中有上一个项目的 app.ts
,会看到权限错误:
因为在默认情况下 Deno 是不允许访问文件系统的。使用 --allow-read=./
可以授予对当前文件夹的访问权限:
deno run --allow-read=./ https://deno.land/std/examples/cat.ts app.ts
Deno 是否有 Express/Hapi/Koa ?
当然有类似的项目:
示例:使用 Oak 构建 REST API
我想举一个简单的例子,说明如何用 Oak 构建 REST API。 Oak 之所以有趣,是因为它受到了流行的 Node.js 中间件 Koa 的启发,因此,如果你以前用过,将会非常熟悉。
要构建的API非常简单。我们的服务器将会在内存中存储带有名称和年龄的狗的列表。
我们想:
- 添加新狗
- 列出狗
- 获取特定狗的详细信息
- 从列表中删除一条狗
- 更新狗的年龄
我们将用 TypeScript 进行这些操作,当然你也可以用 JavaScript 编写 API —— 只需去掉类型就可以了。
创建一个 app.ts
文件。
首先从 Oak 导入 Application
和 Router
对象:
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
然后得到环境变量 PORT 和 HOST:
const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'
默认情况下,我们的程序将运行在 localhost:4000 上。
接下来创建 Oak 应用程序并启动它:
const router = new Router()
const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Listening on port ${PORT}...`)
await app.listen(`${HOST}:${PORT}`)
现在程序应该可以正常编译了。
运行
deno run --allow-env --allow-net app.ts
然后 Deno 将会下载依赖项:
最后侦听 4000 端口。
下次运行命令时,Deno 将会跳过安装部分,因为这些软件包已经被缓存了:
在文件开始,我们为狗定义一个接口,然后声明一个初始的 Dog 对象 dogs
数组:
interface Dog {
name: string
age: number
}
let dogs: Array<Dog> = [
{
name: 'Roger',
age: 8,
},
{
name: 'Syd',
age: 7, },
]
现在开始实现 API。
准备就绪。在创建路由器后,让我们添加一些将被调用的功能:
const router = new Router()
router
.get('/dogs', getDogs)
.get('/dogs/:name', getDog)
.post('/dogs', addDog)
.put('/dogs/:name', updateDog)
.delete('/dogs/:name', removeDog)
看到了吗?我们定义了以下这些:
GET /dogs
GET /dogs/:name
POST /dogs
PUT /dogs/:name
DELETE /dogs/:name
让我们一一实现。
从 GET/dogs
开始,它返回所有狗的列表:
export const getDogs = ({ response }: { response: any }) => {
response.body = dogs
}
接下来,是通过名称检索一只狗的方法:
export const getDog = ({
params,
response,
}: {
params: {
name: string
}
response: any
}) => {
const dog = dogs.filter((dog) => dog.name === params.name)
if (dog.length) {
response.status = 200
response.body = dog[0]
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
这是我们添加新 dog 的方法:
export const addDog = async ({
request,
response,
}: {
request: any
response: any
}) => {
const body = await request.body()
const dog: Dog = body.value
dogs.push(dog)
response.body = { msg: 'OK' }
response.status = 200
}
注意,我现在使用 const body = await request.body()
来获取 body 的内容,因为 name
和 age
的值是作为 JSON 传递的。
这是更新狗年龄的方法:
export const updateDog = async ({
params,
request,
response,
}: {
params: {
name: string
}
request: any
response: any
}) => {
const temp = dogs.filter((existingDog) => existingDog.name === params.name)
const body = await request.body()
const { age }: { age: number } = body.value
if (temp.length) {
temp[0].age = age
response.status = 200
response.body = { msg: 'OK' }
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
这是从列表中删除狗的方法:
export const removeDog = ({
params,
response,
}: {
params: {
name: string
}
response: any
}) => {
const lengthBefore = dogs.length
dogs = dogs.filter((dog) => dog.name !== params.name)
if (dogs.length === lengthBefore) {
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
return
}
response.body = { msg: 'OK' }
response.status = 200
}
以下是完整的代码:
import { Application, Router } from 'https://deno.land/x/oak/mod.ts'
const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'
interface Dog {
name: string
age: number
}
let dogs: Array<Dog> = [
{
name: 'Roger',
age: 8,
},
{
name: 'Syd',
age: 7,
},
]
export const getDogs = ({ response }: { response: any }) => {
response.body = dogs
}
export const getDog = ({
params,
response,
}: {
params: {
name: string
}
response: any
}) => {
const dog = dogs.filter((dog) => dog.name === params.name)
if (dog.length) {
response.status = 200
response.body = dog[0]
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
export const addDog = async ({
request,
response,
}: {
request: any
response: any
}) => {
const body = await request.body()
const { name, age }: { name: string; age: number } = body.value
dogs.push({
name: name,
age: age,
})
response.body = { msg: 'OK' }
response.status = 200
}
export const updateDog = async ({
params,
request,
response,
}: {
params: {
name: string
}
request: any
response: any
}) => {
const temp = dogs.filter((existingDog) => existingDog.name === params.name)
const body = await request.body()
const { age }: { age: number } = body.value
if (temp.length) {
temp[0].age = age
response.status = 200
response.body = { msg: 'OK' }
return
}
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
}
export const removeDog = ({
params,
response,
}: {
params: {
name: string
}
response: any
}) => {
const lengthBefore = dogs.length
dogs = dogs.filter((dog) => dog.name !== params.name)
if (dogs.length === lengthBefore) {
response.status = 400
response.body = { msg: `Cannot find dog ${params.name}` }
return
}
response.body = { msg: 'OK' }
response.status = 200
}
const router = new Router()
router
.get('/dogs', getDogs)
.get('/dogs/:name', getDog)
.post('/dogs', addDog)
.put('/dogs/:name', updateDog)
.delete('/dogs/:name', removeDog)
const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
console.log(`Listening on port ${PORT}...`)
await app.listen(`${HOST}:${PORT}`)
更多资源
Deno 官方网站是 https://deno.land
可在 https://doc.deno.land 和 https://deno.land/typedoc/ind... 上得到 API 文档。
awesome-deno https://github.com/denolib/aw...
一些小花絮
- Deno 提供了一个内置的
fetch
实现,与浏览器中的相匹配 - Deno 与 Node.js stdlib 有一个兼容层正在进行开发中
最后的话
希望你喜欢这个 Deno 教程!
本文首发微信公众号:前端先锋
欢迎扫描二维码关注公众号,每天都给你推送新鲜的前端技术文章
欢迎继续阅读本专栏其它高赞文章:
- 深入理解Shadow DOM v1
- 一步步教你用 WebVR 实现虚拟现实游戏
- 13个帮你提高开发效率的现代CSS框架
- 快速上手BootstrapVue
- JavaScript引擎是如何工作的?从调用栈到Promise你需要知道的一切
- WebSocket实战:在 Node 和 React 之间进行实时通信
- 关于 Git 的 20 个面试题
- 深入解析 Node.js 的 console.log
- Node.js 究竟是什么?
- 30分钟用Node.js构建一个API服务器
- Javascript的对象拷贝
- 程序员30岁前月薪达不到30K,该何去何从
- 14个最好的 JavaScript 数据可视化库
- 8 个给前端的顶级 VS Code 扩展插件
- Node.js 多线程完全指南
- 把HTML转成PDF的4个方案及实现
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。