Deno 环境下的 TypeScript 开发

做者:Flavio Copes

翻译:疯狂的技术宅javascript

原文:https://www.freecodecamp.org/...html

未经容许严禁转载前端

The Deno Handbook: A TypeScript Runtime Tutorial with Code Examples

我每周都会探索一些新的项目,但不多会有像 Deno 这样吸引个人。java

在本文中,我会让你快速了解 Deno,并把它与 Node.js 进行比较,以此构建你的第一个 REST API。node

什么是Deno?

Deno 就像 Node,可是在不少方面都获得了深刻的改善。先从 Deno 功能列表开始:git

  • 它基于 JavaScript 语言的现代功能
  • 它有全面的标准库
  • 它以 TypeScript 为核心,以许多不一样的方式带来了巨大的优点,包括一流的 TypeScript 支持(你没必要单独编译 TypeScript,它由 Deno 自动完成)
  • 它包含 ES 模块
  • 没有包管理器
  • 它有一流的 await
  • 内置测试功能
  • 它尽量地与浏览器保持兼容,例如提供内置的 fetch 和全局 window 对象

咱们将在本指南中探索全部这些功能。程序员

在你开始使用 Deno 并了解了其功能以后,Node.js 看起来就像是“旧的”东西。github

特别是由于 Node.js API 是基于回调的,它是在 promise 和 async/await以前编写的。 Node 中没有可用于修改的余地,这种修改的代价将会是巨大的。因此咱们只能用回调或大量的 API 调用。web

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

img

一旦完成,你将能够访问 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 upgrade deno to the newest version
  • upgrade 升级到最新版本的 deno

能够运行 deno help 来获取命令的特定其余说明,例如 deno run --help

就像帮助所说的那样,咱们能够用这个命令使 deno 来启动REPL(Read-Execute-Print-Loop),而无需任何其余操做。

img

这与运行 deno repl 相同。

这个命令的一种更常见的使用方法是执行包含在 TypeScript 文件中的 Deno 程序。

你能够同时运行 TypeScript(.ts)文件与 JavaScript(.js)文件。

若是你不熟悉 TypeScript,请不要担忧:尽管 Deno 是用 TypeScript 编写的,可是你也能够用 JavaScript 编写“客户端”程序。

第一个 Deno 程序

让咱们运行第一个 Deno 应用程序。

我感到很是惊奇的是,甚至不须要写一行代码代码——你能够从任何 URL 运行命令。

Deno下载程序,进行编译,而后运行:

img

固然,从互联网上运行任意代码不是一种建议作法。不过咱们是从 Deno 官方网站上运行它的,另外,Deno 还有一个沙箱,能够阻止程序执行你不但愿作的任何事情。稍后再详细介绍。

这个程序很是简单,只需调用 console.log() 便可:

console.log('Welcome to Deno 🦕')

若是用浏览器打开 URL https://deno.land/std/example... ,则会看到如下页面:

img

奇怪吧?你可能但愿拿到 TypeScript 文件,可是却获得了一个网页。缘由是 Deno 网站的 Web 服务器知道你正在使用浏览器,并为你提供了更加用户友好的页面。

例如,用 wget 下载相同的UR,它要求使用 text/plain 版本而不是 text/html

img

若是你想再次运行该程序,那么如今它已由 Deno 缓存,不须要再次下载:

img

你可使用 `--reload 标志来强制从新加载原始源:

img

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.tscurl的简单实现,可打印做为参数输入的 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 扩展(我尝试时有另外一个名称相同,但已弃用的扩展——未来可能会消失)

img

该扩展将提供一些可以给 VS Code 带来好处的实用工具,帮助你编写程序。

下面在文件夹中建立一个 app.ts 文件,并粘贴上面的代码:

img

而后用 deno run app.ts 运行:

img

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

而且这些都是自动导入的。

尽管最后咱们遇到了一个问题:

img

怎么回事?咱们遇到了一个权限被拒绝的问题。

接下来要谈谈沙箱。

Deno 沙箱

以前我曾经提到过,Deno 的沙箱能够防止程序执行你不但愿作的任何事情。

这是什么意思?

Ryan 在 Deno 简介演讲中提到过,有时你想在 Web 浏览器以外运行 JavaScript 程序,但又不想让它访问系统上任何内容,或使用网络与外界对话。

没有什么方法可以阻止 Node.js 应用获取你系统上的 SSH 密钥或任何其余的东西,并将其发送到服务器。这就是为何咱们一般只从受信任的源安装 Node 软件包的缘由。可是,咱们怎么知道本身使用的项目是否遭到黑客入侵,而其余人是否被黑客入侵呢?

Deno 尝试复制与浏览相同的权限模型。除非你明确容许,不然在浏览器中运行的 JavaScript 不会在你的系统上作任何使人做呕的事情。

回到 Deno,若是一个程序想要像之前那样访问网络,那么咱们须要给它权限。

能够经过在运行命令时传递一个标志来实现,在本例中是 --allow-net

deno run --allow-net app.ts

img

如今该程序能够在端口 8000 上运行 HTTP 服务器了:

img

有不少容许 Deno 解锁其余功能的标志:

  • --allow-env 容许环境访问
  • --allow-hrtime 容许高精度的时间测量
  • --allow-net = 容许网络访问
  • --allow-plugin 容许加载插件
  • --allow-read = 容许文件系统读访问
  • --allow-run 容许运行子进程
  • --allow-write =容许文件系统写访问
  • --allow-all 容许全部权限(与 -A 相同)

netreadwrite 的权限能够是细粒度的。例如你能够用 --allow-read=/dev 来容许从特定目录中读取

格式化代码

我喜欢 Go 语言的一个缘由是 Go 编译器附带的 gofmt 命令。全部的 Go 代码看起来都同样。每一个人都在用 gofmt

JavaScript 程序员习惯于运行 Prettierdeno fmt 其实是在后台运行的。

假设你有一个格式很乱的文件,以下所示:

img

运行 deno fmt app.ts,它会自动被正确的格式化,还会在缺乏分号的地方自动添加:

img

标准库

尽管这个项目还很年轻,但 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,会看到权限错误:

img

由于在默认状况下 Deno 是不容许访问文件系统的。使用 --allow-read=./ 能够授予对当前文件夹的访问权限:

deno run --allow-read=./ https://deno.land/std/examples/cat.ts app.ts

img

Deno 是否有 Express/Hapi/Koa ?

固然有相似的项目:

示例:使用 Oak 构建 REST API

我想举一个简单的例子,说明如何用 Oak 构建 REST API。 Oak 之因此有趣,是由于它受到了流行的 Node.js 中间件 Koa 的启发,所以,若是你之前用过,将会很是熟悉。

要构建的API很是简单。咱们的服务器将会在内存中存储带有名称和年龄的狗的列表。

咱们想:

  • 添加新狗
  • 列出狗
  • 获取特定狗的详细信息
  • 从列表中删除一条狗
  • 更新狗的年龄

咱们将用 TypeScript 进行这些操做,固然你也能够用 JavaScript 编写 API —— 只需去掉类型就能够了。

建立一个 app.ts 文件。

首先从 Oak 导入 ApplicationRouter 对象:

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 将会下载依赖项:

img

最后侦听 4000 端口。

下次运行命令时,Deno 将会跳过安装部分,由于这些软件包已经被缓存了:

img

在文件开始,咱们为狗定义一个接口,而后声明一个初始的 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
}

img

接下来,是经过名称检索一只狗的方法:

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}` }
}

img

这是咱们添加新 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
}

img

注意,我如今使用 const body = await request.body() 来获取 body 的内容,由于 nameage 的值是做为 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}` }
}

img

这是从列表中删除狗的方法:

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
}

img

如下是完整的代码:

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.landhttps://deno.land/typedoc/ind... 上获得 API 文档。

awesome-deno https://github.com/denolib/aw...

一些小花絮

  • Deno 提供了一个内置的 fetch 实现,与浏览器中的相匹配
  • Deno 与 Node.js stdlib 有一个兼容层正在进行开发中

最后的话

但愿你喜欢这个 Deno 教程!


本文首发微信公众号:前端先锋

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎扫描二维码关注公众号,天天都给你推送新鲜的前端技术文章

欢迎继续阅读本专栏其它高赞文章:


相关文章
相关标签/搜索