原文:The Deno Handbook: A TypeScript Runtime Tutorial with Code Examples
What is Deno
Node.js替代品 , 服务端JavaScript生态系统 , 与Node.js相比在许多方面进行了改进.
Deno特性:
- 基于
JavaScript的现代特性 - 可扩展的标准库
Deno使用Rust和TypeScript编写并因此在多方面受益良多 , 天然支持TypeScript, 自动编译TypeScript文件- 支持
ES Module - 无需包管理
[package manager] - 支持
await, 实现了top-level await - 内置测试设施
- 尽可能兼容浏览器端 , 如提供了内置的
fetch和全局对象window
Node.js API基于callback回调函数 , 无法优雅地利用promises and async/await.
而Deno全面支持TypeScript以及现代标准库(Deno可承载所有使用现代技术书写的代码 , 因此无需维护向后兼容) , 相信未来会流行起来.
与Node.js的异同
同
- 基于
chrome V8 Engine发展而来 - 使用
JavaScript开发服务端
异
Node.js编写自C++ and JavaScript,Deno编写自Rust and TypeScriptNode.js提供官方的npm包管理器 , 而Deno无包管理器但却允许你直接从URLs导入任意ES ModuleDeno在其所有的APIs及标准库中使用现代ECMAScript特性 , 而Node.js使用基于回调函数的标准库且无相关的升级计划Deno通过权限[permissions]提供了安全层沙盒. 用户可以通过设置flags命令参数控制程序的访问权限 ;Node.js程序可以访问用户所能访问到的任意内容- 沙盒可阻止程序做任何你不允许其做的事情 , 如是否允许程序访问本地系统的内容或使用网络与外界通信 ,
deno run --allow-net app.ts
- 沙盒可阻止程序做任何你不允许其做的事情 , 如是否允许程序访问本地系统的内容或使用网络与外界通信 ,
- 从长远看 ,
Deno有将程序在无需外部依赖的前提下编译为可执行文件的预想可能性 , 类似Go, 该设想将带来革命性的影响 !
Deno 标准库
archive: tar archive utilitiesasync: async utiltiesbytes: helpers to manipulate bytes slicesdatetime: date/time parsingencoding: encoding/decoding for various formatsflags: parse command-line flags--allow-envallow environment access--allow-hrtimeallow high resolution time measurement--allow-net=<allow-net>allow network access--allow-pluginallow loading plugins--allow-read=<allow-read>allow file system read access--allow-runallow running subprocesses--allow-write=<allow-write>allow file system write access--allow-allallow all permissions (same as -A)
fmt: formatting and printingfs: file system APIhash: crypto libhttp: HTTP serverio: I/O liblog: logging utilitiesmime: support for multipart datanode: Node.js compatibility layerpath: path manipulationws: websockets
基于 Deno 的框架
Demo : use Oak to build a REST API
Create app.ts
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";
const router = new Router();
const app = new Application();
define an interface for a Dog
interface Dog {
name: string;
age: number;
}
let dogs: Array<Dog> = [
{
name: "Roger",
age: 8,
},
{
name: "Syd",
age: 7,
},
];
implement the API & add to Router
const router = new Router()
router
.get('/dogs', getDogs)
.get('/dogs/:name', getDog)
.post('/dogs', addDog)
.put('/dogs/:name', updateDog)
.delete('/dogs/:name', removeDog)
const getDogs = ({ response }: { response: any }) => {
response.body = dogs;
};
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}` };
};
const addDog = async ({
request,
response,
}: {
request: any;
response: any;
}) => {
const body = await request.body();
console.log(body, JSON.parse(body.value));
const dog: Dog = body.value;
dogs.push(dog);
response.body = { msg: "OK" };
response.status = 200;
};
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}` };
};
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;
};
run app.ts
deno run --allow-env --allow-net app.ts