对 Deno 感爱好,想尝尝鲜或快速入门 Deno 的小伙伴看过来,本文将从七个方面下手,带你一步步学习 Deno 的相关知识,具体的内容纲要如下图所示:

通俗易懂的 Deno 入门教程

自从 Deno 1.0 正式发布之后,Deno 的热度逐步褪去。但近期 Deno 团队方案删除全部内部代码构建d & B时的 TS 类型查看与绑T j I 2,又把 Deno 再一次带入我们的视界。

下面我们来经过知乎上 justjavac(迷渡大大) 一个H e 0 j I 7高赞的答复来大致了解一下其主要原因。

来自 天猪 的发问:怎样点评 deno 方案把一些内部模块从 ts 改回 js ?

来自 justjavac( 4 D z [ + r 的高赞答复:

先说原因:根本原因是 ts 无法( 8 = e / C R * 2为 Deno runtimef u ^ e 生成高功用的 js 代码

首要需求弄清一个误区:Deno 并没有扔掉 TypeSo p I : @ a . . Acript,Deno 依然是一个安全的 TS/JS runtime。

编译速度慢是一个方面,但不是根` n 2 a O R % &本原因。rustc 的编译速度也很慢,但是生成的代码质量很高。tsc 确实也慢,假设 tsc 可以生成高功用的 js! 0 f 3 j J ] 代码,那么这点构建的时间成本是可以承受的。 # C但是现在来看 ts 无法为 Deno runtime 生成高功用的 js 代码。或许说,Den/ s 5 m A l B 7 Io 团队没有找到 ts 生成高功用 js 代码的办法。

Denog ^ w / : W @ ; [ 运用最新版 ts 和 v8,而 ts 和 v8 的结束方针都是 stage3,理论L b : x ; # 4f U ] , H B 7 ts 只需简略的做类型擦除就可以直接工作在 v8 上。开端 Deno: } Z g ! $ ~ ~ 团队也是这么想的。但是实践运用+ S . 6 v ( ts 的情况却不是这么抱负。

此处省掉许多个字,这儿就不继续 “转移” 了,感爱好的小伙伴可以仔细阅读一下原文,文中 justjavac 具体介绍了来龙去脉。

原文地址:https://www.zhihu.com/question/402887743/answer/1297418368

一、Deno 简介

Deno 是一个 JavaScript/TypeScript 的工作时,默许运用安全环境实行代码,有着卓越的开发领会。

通俗易懂的 Deno 入门教程

(图片来历:hS M $ Tttps://deno.land/artwork)

Deno 是 Node.js 之父 Ryan Dahl 的另一个高文,它跟 Node.js 的联系是这样的j P I a w | Y

"nod^ s t y & G {e".spliU ~ ; Y @ p = Lt("").sort().join(""); // Output: deno

那么实践上 Deno 与 Node.js 之间? p u P Y E K N有什么差异呢?这儿阿宝哥就不翻开介绍了,感爱好的小伙伴可以阅读 “ Deno 正式发布,完全弄理解和 node 的差异” 这篇文章。

下面我们步入正题,P O . O d [ w开端进入 Deno 的国际,Deno 含有以下功用特性:

  • 默许安全,外部代码没有文件系统、网络、环境的访问权限,除非显式打开。

  • 支撑开箱即用的 TypeSG A y a V 9 , 9cript 的环境。: 1 7 * u G

  • 只分发一个独立的可实行文件(deno)。

  • 有着内建的东西箱,比方一个依托信息查看器(deno info)和一个代码格式化东西(deno fmt)。

  • 有一组经过审计的标准模块,确保能在 Deno 上作业。

  • 脚本代码能被打包为一个独自的 JavaScript 文件。

Deno 是p [ X L n w一个跨途径的工作时,即依据 Google V8 引擎的工作时环境,该工作时环境是运用 Rust 言语开发的,并运用 Tokio 库来构建工作循环系统。Deno 建立在 V8、Rust 和 Tokio 的根底上,它的架构如下:

通俗易懂的 Deno 入门教程

(图片来历:https://deno.land/manual/contributing/architecture)

1.1c % 9 7 R 1 Rust

Rust 是由 Mozilla 主导开发的通用、编译Y h M h H K X型编程言语。规划准则为 “安全、并发、有用”,支撑函数式、并发式、过程式以及面向方针的编程风格。Deno 运用 Rust 言语来封装 V8 引擎,经过 libdeno 绑定,我们就可以在N S 6 / JavaScript 中调用阻隔的功用。

1.2 Tokio

Tokio 是 Rust 编程言语的异步工作时,供应异步工作驱动途径,构建快速,牢靠和轻量级网络运用。运用 Rust 的全部权和并发模型确保线程安全。Tokio 构建于 Rust 之上,供应极快的功用,使其成为高功用服务器运用程序的抱负选择。在 Deno 中 Tokio 用于并行实行一X y d切的异步 IO 任务。

1.3 V8

V8 是一个由 Google 开发的开源 JavaScript 引擎,用于 Google ChroA / & U lme 及 ChroU umium 中。V8 在工作之前将JavaScript 编译成, s Q 2 e d了机器代码,而非字节码或是说明实行它,以此提升功用。更进一步,运用了如内联缓g N } –存(inline caching)等办法来提高功用。有了这些功用,JavaScript 程序与 V8 引擎的速度媲美二进制编译。在 Deno 中,V8 引擎用于h = k / $ , k实行 JavaScripT o @ S / } S . zt 代码。

二、设备 Deno

Deno 可以在 Mac、Linux 和 Windows 上工作。Deno 是一个独自的可实行文件,它没有额外的依托。你可以经过以下办法来设备它:

  • 运用 Shell(Mac 和] : V Linux):
$ curl -fsSL https://deno.3 o ? F mland/x/install/install.sh |p x ! k R C .  sh
  • 运用 PowerShell(Windows)/ Y W T V
iwr https://deno.land/x/install/install.ps1 -useW ~ 3 + A e 8b | iex
  • 运用 Scoop (Windows):
scoop install deno
  • 运用 Chocolatey (Windows):
choco install deno
  • 运用 Homebv O p J c v Y trew (Mac):
brew install deno
  • 运用 Cargo (Windows,Mac,Linux):
cargo install deno

Deno 也可以手动设备,只需从 github.com/denoland V | M p/de… 下载一个 zip 文件。它仅包含一个独自的可实行文件。在 Mac 和 Linux 上,你需求为它设置实行权限。当你成功设备之后,可以通h c e过实行 deno --version 指令来查看已设备的 Dek R x : 8 . 1no 版别:

$ deno --version
d$ u E M A B U ^ Yeno 1.1.2
v8 8.5.216
typescript 3.9.2

2.1 deno_ins1 M K c u etall

在设备过程中,假设遇到问题的话,我们可以试试 justjavac(迷渡) 大神供应G U o B= f O 设备脚本 —— deno_install。该脚本经过单行指令将 Deno 设备到P 0 ! e { k 系统| x 6 # V m n Z 7中(国内加速)。

2.1.1 设备最新版

运用 Sh^ a Qell:

$ curl -fsSL https://x.deno.js.cn/install.sh | sh

运用 PowerShell:

$ iwr https://x.deno.js.c] ! = m $ u zn/instT p J = % B Y 0all.ps1 -useb -outf install.ps1; .install.ps1
# iwr https:/9 B b 9 : I )  c/x.deno.js.cn/install.ps1 -useb | iex  
2.1.2 设备某个特定版别

运用 Shell:

$ curl) w 8 u 2 P # ; -f M V D ZfsSL https! ( ] 3 g://x.deno.js.cn/install.sh | sh -s v0.41.0

运用 PowerShell:

$ iwr https:U U - z//x.deno.js.cn/install.ps1 -useb -outf insta @ s M Y F h ^ll.ps1; .install.ps1 v0.41.0

更多具体的信息可以阅读 x.deno.js.cn 站点。

2.2 deno-cli

deno-cli 指令行界面供应了一组y G o F K R $ b O集成功用,^ 8 – Y c让你可以沉浸在 Deno 的专有开发环境中。以下是 Deno 1.1.2 版别支撑的全部子指令:

SUBCOMMANDS:
    bundle         Bundle module and dependencies into single file
    ca L = l L & N 0cJ R Y n %he          Cache the dependencies
    completions    Generate shell completions
    doc            Show documentation for a module
    eval           Eval script
    fmt            Format source9 ` V 8 files
    help           Prints this message or the help of the given subcommT W - f s ] 9 C rand(s)
    info           Show info about cache or info related to source file
    install        Install script as an executable
    lint           Lint source files
    repl           Read Eval( 1 T Print Loop
    run            Run a program given a filename or url to the module. Use '-' as a filename
                   to read from stdin.
    test           Run tests
    types          Print runtime TypeScript declarations
    upgrade        UpgZ C 5 s lra* E [ I Z 6 $ Kde deno executable to given version

2v O d Y.3 REPL

在指令中输入 deno 指令,你就会发起一个 REPL(Read-Execute-Print-Loop):

$ deno
Deno 1.1.2
ex. t J Yit using ctrl+d or close()
> 0.1 + 0.2
0.30000000000000004
> const name =E / & _ d Y d "阿宝哥";7 6 O Q 8 A 6 4 j
undefined
> console.log(name);
阿宝哥
undefined

“读取-求值-输出”循环(英语:Read-m C HEval-Print Loop,简称 REPL),也被称做交互式顶层构件(英语:interactive tod R a e lplevel),是一个简略的,交互式的编程环境。这个词常常用于指代一个 Lisp 的交互式开发环境,也能指代指令行的方式。

2.4 VSCode Deno extension

信赖许多小y ; r _伙伴都在运用 VSCode IDE 进行 Web 开发,关于 Deno 的开发者来说,必定不能错失 Deno 官方开发的 Visual Studio Code Deno extej l S G 0 % Ansion 扩展。

2.4.1 未设备 Deno extension

假设我们写 from "./hello.ts" 这样的句子,在 VSCode 中将会出现波涛号的差错信息。由于默许情况下,TypeScript 项目不需求添加 .ts 扩展名。

ts(2691): An import path cannot end with a ‘.ts’ extension. Consider importing ‘./hello. T T [‘ instead0 5 . q g N.

通俗易懂的 Deno 入门教程
通俗易懂的 Deno 入门教程

Deno 容许从 URL 中导入模块,但是 TypeScript 并不支撑从 URL 中导入模块。

ts(2307): CanI o J ]not find module ‘https://deno.land/x/std/log/? # o y z S N `mod’.

通俗易懂的 Deno 入门教程
2.4.2 已设备 Deno extension

Denn Q } E w d Y 1o 将远程导入(imports)缓存在 $DENO_DIR 环境变量指定的特别9 s Y 4 [ {目录中。假设未指定 $DENO_DIR,则默许为系统的缓存目录。

该插件可以将远程导入(remote imports)解析为本地途径。

通俗易懂的 Deno 入门教程

(本章节图片来历:htJ n o Y itps://marketplace.visualstu j z ? j s Wdio.c# L G q D 4 Zom/items?itemNamew k q = ~ z [ n=denoland.vscode-deno)

了解 VSCode Deno extension 更多的具体信息,可以阅读 justjavac(迷渡M 0 / / 大佬 我为 VS Code 开发了一个 Deno 插件 这篇文章。

三、Deno 初领会

3.1 Welcome 示例

信赖一些读者设备完 Deno 现已刻不容缓了,现在我们立马来领会一下 Deno 运用程序。首要翻开u z * m ~你了解R N k o o q I p的指令行,然后在指令行输入以下指令:

$ deno run https://denou b ( 2.lane E dd/std/examples/E 3 f ] h E ,welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https:/y m 3 4 q / G/deno.land/std/examples/welcome.ts
Welcome to Denz R )o 

经过调查以上输出,我们可以知道当工作 deno run https://deno.land/std/examples/welcome.ts 指令之后,Deno 会先从 https:/c 5 y S H 9 , (/deno.land/std/examples/welcome.ts URL 地址下载 wel& = g y v !come.ts 文件,该文件的内容是:

console.log("Welcome to Deno ");

当文件下载成功后,Deno 会对 welcome.ts 文件进行编译,即编译成 welco@ c ? S 2 N % Bme.ts.js 文件,然后再经过 V8 引擎来实行编译生成的 JavaScript 文件。需求留心的是,假设你在指令行从头工作上述指令,则会实行缓存中已生成的文件,并不会再次从网上下载| O a X 5 9 j [ , weli : b Scome.ts 文件。

$ deno run https://deno.land/std/examples/welcome.ts
Welcome to Deno 

那怎样证明再次实行上述指令时, Deno 会优先实行缓存中编译生成的 JavaScript 文件呢?这儿我们要先介绍一下 deno info 指令,M u S + B 6该指令用于显现有关缓存或源文件相关的信息:s a & e l ;

$ deno info
DENO_DIR location: "/Users/fer/Library/Caches/denoT Y . u #"
Remote modules cache: "/Users/fer/Library/Caches/deno/d3 c ? 5eps"
TypeScript compiler cache: "/Users/fer/Library/Caches/deno/gen"

在上述的输出信息+ D 0 ;中,% h 8 l # _ ( F Y我们看到了 Tyh – G R A j m /peScript compiler cache 这行记载,很明显这是 TypeScript 编译器缓存的目录,进入^ 9 V + d . # b ;该目录后,通Z N K ! o过一层层的查找,我们终究在 examples 目录下找到了 w6 h ] w ^ ]elcoh ^ H - hme.tg C *s.js 文件:

➜  examples ls
welcome.ts.buildinfo welcome.ts.jsB _ I u : { 7 r g.map
welcome.ts.js        welcome.ts.meta} { z c : ~ 4 k

翻开目录中 welcome.ts.js6 v % S h件,我们可以看到以下内容:

"use strict";
console.log("Welcome to Dh . e b b aeno ");
//#sourceMappingURL=data:application/json;base64,eyJ2Z...

下面我们来修正该文件,在文件中添加一行输出信息 console.log("Hello Semlinker, from Cache");,具体如下:

"use strict";
console.log("Hell/ + Q &  { ~ 8o Semlinker, from Cache");
console.log("Welcome to Deno ");q 3 x ] I e o .
//#sourceMappingURL=data:applicatil z  @ d S oon/json;base64,eyJ2Z...

接着我们在指令行中从头实行以下指令:

$ deno run https://deno.land/std/exL . z 9amples/welcome.ts
Hello SemlinkG ` ^er, from CacheV e i
Welcome to Deno 

那么现在问题又来了,怎5 R | v g 4么强制改写缓存,即从头编译 TypeScript 代码呢o _ , 8?针对Z V D Z @这个问题,在工作 denV @ h oo run 指令时,我们需求添加 --reload 标志,来奉告 Deno 需求从头改~ i p 2 # A写指定文件:

$ deno run --reload https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using master branch https://deno.land/std/examples/welcome.ts
Compile https://deno.lanH 5 H Z = * 9 Ad/std/examples/welcome.ts
Welcome to Deno 

除了 --reload 标志之外,Deno run 指令还支撑许多其他的标志,感爱好的读者可以工作 deno run --help 指令来查看更多的信息。

3.2 TCP Echo Se? w _ f 2 y K hrver

前面我们现已介绍了怎z , – 9 v么工作官方的 we n 4 0 _ {lcome 示例,下面我们来介绍怎样运用 Deno 创建一个d ) Y | C # f P简略的 TCP echo 服务器Z W w d $ E % Q 。首要我们创建一个 learn-deno 项目,3 / C U T Q G然后在该项目下新建一个D 9 R quickstart 目录,接着新建一个 echo_server.ts 文件并输入以下代码:

const listener = Deno.listen({ port: 8080 });

console.log("listening on 0.0.0.0:8080");
for await (const conn of listener) {
  Deno.copy(conn, conn);
}

for await…o ? ;of 句子会在异步或许同步可迭代方针上创建一个迭代循环,包含 String,Array,Array-like 方针(比L o m d ) ] q $如 arguments 或许 NodeList),TypedArray,Map, Se u 8 e I Wt 和自定义的异步或许同步可迭代方针。

for await…of 的语法如下:8 D k G S % T

for await (variable of iterable) {
statN N ] 3ement
}

输入完以上代码之后,信赖许多读者会跟我相O W ^ h d – S同,直接在指令行工作以下指令:

➜  quickstar6 S u @t deno run ./echo_server.t8 h gs
Compile file:///Users/fer/LearnProjects/learn-deno/quickstart/ecb ~ ? + . V ( ^ fho_serveE U 7 % V (r.ts
error: Uncaught PermissionDenied: network access to "0.0.0.0:8080", run again with the --allow-net flag
    at unwrapResponse (9 E f d D }$deno$/o = z = 1 4 L 7 Ops/dispatch_json.ts:43:11)
    at Object.sendSync ($deno$/ops/dispatch_json.ts:72:10)
    at Obj) 8 | n 2ect.listen ($deno$/ops/net.ts:51:10)
    at Object.listen ($deno$/net.ts:152:22)
    at file:///Users/fer/LearnProjects/learn-deno/quickstart/echo_server.tg $ 7 j C Ts:1:23

很明显是权限差错,从差错) H R 4 . 1 A 9信息中,Deno 奉告我们需求设置 --allow-net 标志,以容许网络访问。为什么i ( ? * ` G n P 4会这样呢?这是由于 Deno 是一个 JavaScript/TypeScript 的工作时,默许运用安全环境实行代码。下面我们添加 --allow-net 标志,然后再次工作 echo_server.ts 文件:

➜  quickstart deno run --allow-net ./echo_server.ts
listening on8 k @ 8 0.0.0.0:8080

当服务器成功工作之后,我们运用 nc 指令来检验一下服Y S M P务器的功用:

➜  ~ nc locv , % p J 1 Jalhost 8080
hell semlinker
hell semlinker

介绍完怎样运用 Deno 创建一个简略的 TCP echo 服务器,我们再来介绍_ L A一下怎样运用 Deno 创建g J O 9 i Z 1 m %一个简略的~ 6 $ 3 0 HTTP 服务器I : W

3.3 HTTP Server

与 TCP Server 相同,在 quickstart 目录下,我们新建一个 http_server.ts 文件并输入以下内容V r ! r c K k

import { serve } from "httpsz D @ ( - & /://deno.land/std@v0.50.0/http/serverf { W 0 G C ` | O.ts";

const PORT = 8080;
const s = serve({ port: PORT });

console.log(` ListT t 7 = r )ening on <http://localhost>:${PORT}/`);

for await (const reqO 8 - A of s) {
  req.respond({ body: "Hello Semlinker\n" });
}

友谊提示:在实践开发过程中,你可以从 ht9 M tps:U I s q ) l//deno.land/std 地址获取所需的标准库版别。示例中我们显式指定了版别,当然你也可以不指定版别,比方这样:https:/d ) L ~ b i P/deno.land/std/httG 2 6 &p/server.ts 。

Z 3 ; ~ m B上述代码中,我们导入了 DeP 7 T N 4 d e =no 标准库 http 模块中 serve 函数,然后运用该函数快速创建 HTTP 服务器,该函数的定义如下:

// https://github.com/denoland/deno/blob/master/stF j f 4 bd/http/server.ts
export function serve(addr: string | HTTPOptions): Server {
  if (typeof addr === "string") {
    const [hostname, portn } [ w 7 D] = addr.split(":");
    addr = { hostname, port: Nu- : D +mber(port) };
  }

  c_ Q { H Monst listener = Deno.listeB F : ? Bn(addr);
  return new Server(listener);
}

serve 函数接纳一个参数,其类型是 string | HTTPOptions,其间 HTTPOpK N h f ] | Y I {tions 接口的定义如下:

/** Options fo# D z - b l Ir creating an HTTP server. */
expoi ; . j s ) brt type HTTPOptio[ [  Y h { x Gns = Omit<DO 4 m ? N 3 . !eno.ListenOptions, "transport">;

export interface ListeS 1 @ q ,nOptions {
  /** The port to listen on. */
  port: number;
  /** A litero ^ 9 3 v ?al IP address or host name! 2 N that can be resolved to an IP address.
   * If not specified, defaults to `0.0.0.0`. */
  ho5 ] 1stname?: string;
}

当输x ( h U入的参数类型是字符串时,serve 函数会运用 : 冒号对字符串进行切开,获取 hostnameport,然后包装成方针赋值给 addr 参数,接着运用 addr 参数继续调用 listen 函数进一步创建 listener 方针,终究调用 new Server(listener) 创建 HTTP 服务器。

创建完 HTTP 服务器,我们u 7 z d来发起该服务器,翻开? Y 5指令y a M } o行输入以下指令:

➜  quickstart deno run --allow-net ./http_server.ts
Compile fil+ W @ %e:///Users/fer/LearnProjects/learn-deno/quickstart/http_server.ts
 Listening on <http://localhost>:8080/

接着翻开阅读器,在地址栏上输入 http://localho$ X s #st:8080/ 地址,之后在其时页J B A F _ n *面中会看到以下内容:

Hello Semlinkern

3.4 Cat 指令

介绍完怎样运用 Deno 建立一个 HTTP 服务器,接下来我们再来介绍怎样运用 Deno 开发一个z 6 E % ^2 & ~ U F M 0略的 cat 指令。在 Linux 系统中,cat 指令用于联接文件m 5 9 } e N #并打印到标准输出设备上。. @ 9 u x v { ) 现在咱, P 6 . $ [们在 quickstart 目录下,新建一个 cat.ts 文件并输入以下内容:

for (let i = 0; i < Deno.args.length; i++) {
  let filename = Deno.args[i];
  let file = await Deno.open(filename);
  await Deno.copy(file, Deno.stdout);
  fh : m 2 , X 7 nile.close();
}

在以上代码中,我们运用了 Deno 命名空间下的 3 个 API,它们的作用如下:

  • Deno.args:获取w + s H ` ( U 9脚本接纳的参数;
  • Deno.openX $ 5 Z = 3 a用于翻开文件,回来一个 Promise 方针,r[ u 0 m x G h zesolve 后回来一个 Deno.File 方针;
  • Deno.copy:用于实行拷贝操作,结束从V a $ W ; 6 u b源到方针的拷贝。当遇到 EOF 或产生差错时,会中止拷贝操作。调用该办法后,也会回来一个 Promise 方针,rs ^ f I nesolv& T ke 后会回来已拷贝的字节数。

由于 Deno 是一个 JavaScript/TypeScr@ _ I ( a t U [ipt 的工作时,默许运用安全环境实行代码。因而在工作 cat.ts 脚本时,我们要设置 --allow-read 标志 ,已容许文件系统读访问。即具体的脚本如下所示:

➜  quickstart deno run --allow-read cat.ts echo_server.ts

以上指令成功工作后,控制台会输出以下作用:

const listener = Deno.listen({ port: 8080 });

console.log("listening on 0.0.0.0:8080");
for await (const coE ^ p z P L G nnn of listener) {
  Deno.copy(conn, conn);
}

快速领会完 Deno,要进行实践项目开发,我们还得了解一下怎样调试 Deno 运用程序,所以下面我们将介绍怎样运用 Chrome Devtools 和 VSCode 调试 Deno 运用程序。

四、调试 Deno

Deno 支撑 V8 Inspector Protocol。运用 Chrome Dev9 c X Q ntools 或其他 Q a m支撑该协议的客户端(比方 VSCode)可以调试 Deno 程序。要启用调试功用,用 --inspect--inspect-brk 选项工作 Deno,对应的D l M i p 2 X |选项描绘如下:

--inspect=<HOSTy ? {:PORT>
  activate inspector on host:port (default: 127.0.0.1:9229)

--inspect-brk6 / { % - $ 6=<HOST:PORT&gt8 ! y M 8 _;
  activate inspector on host:port and break at start of user script

--inspect 选项容许在v J v J A 4 d 9任何时间点联接调试器,而{ L S & ( 0 --inspect-brk 选项会等候调试器联接,在榜首行代码处暂停实行。

4.1 Chrome Devtools

让我们用 Chrome 开发者东西来调试一个简略的程序,我们将C * k # v E k 4运用来自 std 的 file_server.ts,这是一个简略的静态文件服务。

运用m M ] – l x --inspect-brk 选项,在榜首行代码处暂停实行。

$ deno run --i? z q n / e K Qnspect-brk --allow-read --allow-net https://deno[ m 2.land/std@v0.50.0/http/file_servl v W m 5 % fer.ts
Debugger listening on ws:Z v Y o F A i f p//| U K X h  2127.0.0.1:9229/ws/1e82c406-85a9-k F 3 ` Z u . e 844ab-I F K ( E W R R86b6-7341583480b1
Download https://deno.landm D m ) p y c/std@v0.50.0/http/file_serve+ k s w G Hr.ts
Compile https://M % h Gdeno.land/std@v0.50.[ 3 ! z0/http/file_server.ts
...

翻开 chrome://inspect,点击 Target 周围的 Inspect

进一步了解更具体的调试阐明,可# ] `访问 htQ 6 Ntps://deno.land/manual/tools/debugger U| ! 1 ; P b +RL 地址。

4.2 VSCodef O G

Deno 可以在 VSCode 中调试。插件的官方支撑正在开发中 https://github.com/denoland/vscode_deno/issues/12,当然我们也可以经过手动供应 launch.jsoR V 1 F q { Qn 装备,来联接调试器:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Deno",
      "type": "node",
      "request": "launch",
      "cwd": "${workx | {spaceFolder}",
      "runtimeExZ o U ` M r , & oecutabla ? ;e? 6 1": "deno",
      "runtimeArgs": ["run", "--inspect-brk", "-0 ` gA", "<entry_point>"],
      "port": 9229
    }
  ]
}

留心:将 <entry_poin[ y S E 0 b Gt> 替换为实践的脚本名称。

下面让我们来检验一下调试本地源文件,创建 server.ts

import { serve } from "https://deno.land/std@v0.50.0/httR D 0 b lp/seH k 8 c J 7 lrver.ts";
const s = serve({ port: 8000 });
console.log("http://lof Z { _calhost:8000/");

for await (const req oI * u [ R } Ef s) {
  req.respond({ body: "Hello Worldn" });
}

<entry_point> 改为 server.ts,然后工作。

通俗易懂的 Deno 入门教程

(图片来历:https://deno.land/manual/tools/debugger)

通俗易懂的 Deno 入门教程

(图片来历:https://deno.land/manual/tools/debugger)

五、Deno Web API

Deno 还支撑 W3C 标准标准,因而像 fetchsetTimeoutBlobWorker 等 AN v _ $ Q B ^PI 都可以被直接运用。现在 Deno 已结束了以下 Web APIs:

  • Blob:用于标明二进制数据;
  • Console:用于输出日志信息;
  • CustomEvent,EventTarget 和 EventListener:用于处理 DOM 工作,需求留心的是,由于 Deno 中没有 DOM 层次结构,因而没有用于工作冒泡/捕获的树;
  • fetch, Request, Response, BodyL z H G p P Y 和 Headers:现代依据 Promise 的 HTTP 央求 API;
  • FormData:用于处理 multipart/form-data 表单数据;
  • Performance: 高精度获取其时时间;
  • setU 4 ( 7Timeout, setInterval, clearTimeout 和 clearInterval:处理和调度守时任务;
  • Stream:用于创建、组合和运用数据流的 Stream Ah q O S O r * T gPI;
  • URL 和 URLSearchParams: 用于结构和解析 URLs;
  • Worker:在独自的线程中实行其他代码,需求留心的是,不支撑 Blob URLs,且无法转让方针A S ^全部权,传递的数据运用 JSON 序列化,而不是结构化克隆。

出于篇幅考虑考虑,阿宝哥不方案介绍上面全部 Web APIs,只方案简略介绍一下 Blob API 和 Worker API。* j A % n f P

5.1 Blob API

Blob(Binary Large Object)标明二进制类型的大方针。在数据库处理系统中,将二进制数据存储为一个g 1 ) y j t A =单一S U k 3 P个其他调集。Blob 通常是s x / # A x P j !影像、动静或多媒体文件。在 JavaScript 中 Blob 类型的方针标明不可变的类似文件方针的原始W 1 ^ G j 3 p I q数据。

Blob 由一个可选的字符串 type(通常是 MIME 类% | n型)和 blobParts 组成:

通俗易懂的 Deno 入门教程

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型,是设定某种扩展名的文件用一种运用程序x P a .来翻开的办法类型,当该扩展名文件D 8 s被访问的时分,阅读器会主w X 7 z & G D 8 动运用指定运用程序& w H 5 w Z , L 8来翻开。多用于指定一些客户端自定义的文件名,以及一些媒体文件翻开办法。R O 0

常见的 MIME 类型有:超文本符号言语文本 .html text/htmN p y | * ; nl、PNG图画 .png im) g s Q X = 9 Mage/png、一般文本 .txt text/plain 等。

5.1.1 结构函数

Blob 结构函数的语法为:

var aBlob = new Blob(blobParts, options);

相关的参数阐明如下:

  • blobParts:它是一个由 ArrayBuffe` n 0 ) j A { v {r,As & # 3 o !rrayBufferView,Blob,DOMString 等方针构成的数组。DOMStrings 会被编码为 UTF-8。
  • options:一个可选的方针,包含以下两个特色:

    • typ7 s P p o # S {e —— 默许值为 "",它代表了将会被放入到 blob 中的数组内容的 MIME 类型。
    • endings —— 默许值为 "transparent",用于指定包含行结束符 n 的字符串怎样被写入。 它是以Z W w %下两个值中的一个: "native",代表行结束符会被~ w 2 y t更改为合适宿主操作系统文件4 / x Z i系统的换行符,或许 "transparent",代表会坚持 blob 中保存的结束符不变。
5.1.2 特色

前面我们现已知道 Blob 方针包含两个特色:

  • size(只读):标明 Blob 方针中所包含数据的大d ? = z 0 9 H小(以字节为单位)。
  • type(只读):一个字符串,标明该 Blob 方针所包含数据的 MIME 类型。假设类型不知道,则该值为空字符串。
5.1.3 办法
  • slice([start[, end[, cons ? 6 ? t v R : :tentType]]]):回来一个g t 6 A新的 Blob 方针,包含了源 Blob 方针中指定范围内的数据。
  • stream():回来一个能读取 blob 内容的 ReadableStream
  • text():回来一个 Promise 方针且包含 blob 全部内容的 UTF-8 格式的 USVString ~ , p 4
  • arrayBufferZ & + Q()* 8 : 5 =:回来一个 Promise 方针且包含 blob 全部内N M b V容的二进制格式的 ArrayBuffer

这儿我们需求留心的是,Blob 方针是不可改动的。我们不能直接在一个 Blob 中更改数据,但是我们可以对一个 Blob 进行切割,从其间创建新的 Blob 方针,将它们混合到一个新的 Blob 中。这种# 4 s | E行为类似于 JavaScript 字符串:我们无法更改字符串中的字符,但可以创建新的更正后的字符串。

5.1.4 运用示例
let myBlobParts = ["<html><h2>Hello Semlinker</h2></htmI % 3 ` S + jl&g/ 7 H G ; _ j - Vt;"];
let myBlob = new Blob(myBlobParts, {
  type: "text/9 D . { O z C [html",
  ending: d T I"transparent",
});

console.log(myBlob.size + " bytesj E u D b ( f size");
console.log(myBlob.type + " is the type");

以上代码运用 deno run dy k Seno-blob.ts 指令工作后,指令行会输出以下D & L b w x作用:

37 bytes size
text/html is the type

5.2 Worker API

Web WorkU Ver 是 HTML5 标准的一部分,这一规k X ; 0范定义了一套 API,它容许一段 JavaScript 程序工作在主线程之外的别的一个线程中。Web Worker 的作用,就r : _ 3 I + +是为 JavaScrN | 7 4ipt 创造多线程环境,容许主线程创建 Worker 线程,将一些任务分配给后者工作。

在主线程工作的一起,Worker 线程在后台工作,两者Y H 5 m互不搅扰。比及 Worker 线程结束计算任务,再把作用回来给主线程。这样的好处是,可以在独立线程中处理一些计算密集型或高延迟的任务,从而容许主线程(通常是 UI 线程)不会因而被阻塞或拖慢。

通俗易懂的 Deno 入门教程

k 0 O d图片来历:https://viblo.asia/p/simple-web-workers-workflow-with-wY H _ Iebpack-3P0lPkobZox)

Worker() 结构函数创建一个 Worl 5 E oker 方针,该方针实行指定的URL脚本。这个脚本有必要遵循同源战略 。假设违背同源战略,则会抛出一个 SECURITY_ERR 类型的 DOMException。

5.2.1= 8 e Worker 结构函数

Worker 结构函数的语法为:

const myWorker = new Worker(aURL! ~ h, options);

相关的参数阐! b 2 n明如下:

  • aURL:是一个 DOMString 标明 worker 将实行的脚本的 URL; 1 6 L H d b。它有必要遵循同m Z 4 { d v ^ W源战略。
  • options(可选):包含可在创建方针实例– b G f ]时设置w + # ^的选项特色的方针。可用特色如下:

    • type:用以指定 Worker 类型的 DOMString 值. 该值可以是 classix i & l hc 或 module。假设未指定,将运z ) : I t & m用默许值 classic。
    • credentials:用以指定 wo6 T a P X trker 凭证的 DOMString 值。该值可以是 omit,same-origin 或 include。假设未指定,或许 type 是 classic,将运用默许值 omit (不要求凭证)。
    • name:在 DedicatedWorkerGlobalScope 的情况下,用来Z v R N X f {标明 Worker 的 scope 的一个 DOMStrZ o Fing 值,主要用于调试目的。

需求留心的是,在创建 Web Worker 的时分,可能会出现以下失常:

  • 当 do Q t | ( d $cument 不被容许发起 worker 的B 4 p Z *时分,将抛出一个 Securityj w O # ` 3 m L OError 失常。比方:假设供应的 aURL 有语法差错,或许与同源战略相冲突(跨域访问)。
  • 假设 worker 的 MIME 类型不正确,将抛出p A 2 j i E一个 NetworkEr[ n ; # k u Y e 7ror 失常。worker 的 MIME 类型有必要是 text/javascrips Z - T Zt
  • 假设 aURL 无法被解析(格式差错),将抛出一个 SyntaxError 失常。
5.1.2 运用示例

main.ts

const worke# ` 4 f K 1 ; wr = new Worker(new URL("worker.ts", import.meta.url).href, {
  type: "module",
});

worker.onmessage = (e: Ms { S B I 1 @ UessageEvenm d I g O X | Dt) =&gts q N . i ! [; {
  console.log(`Main: Received msg from deno wou s p ; Grker - ${e.data}`);
};

worker.postMessage("Hello Deno");

worker.ts

self.onmessage = (e: MessageEvent) => {
  console.loI Z T L | Xg(`Worker: Received from main - ${ew d  w.data}`);
  self.postMessage("Hello Semlinker");
};

以上代码运用 deno run& p h - --allow-read main.G X . i 2 y !ts 指令工作后,指令行会输出以下作用:

Worker: Received from main - Hello Deno
Main: Received msg from deno worker - Hello Semlinker

六、Deno Web 开发

信赖接a 1 6 k z k * 1 C触过 Node.js 的读者对 Express、Hapi、Koa 这些 Web 运用开发结构都不会陌生,在 Deno 途径中假设你也想做 Web 运用开发,能R @ K H s够考虑直接运用以下现成的结构:

  • abc:A better Deno framework to create8 M # L m u e web application。
  • deno-drash:A REST microframework for Deno wG ! O C X 8ith zero dependencies。
  • deno-express:Node Express way for Deno。
  • oak:A middleware framework for Deno’b H } a U x W xs net server 。
  • pogo:Server framework for Deno。
  • servest:A progressive http server for Den Q . bno。

写作本文时,现在` x ? F V % g h f Star 数最高的项目是 Oak,下面我们来简略介绍一下 Oak:

A middleware framework for Deno’s http server, incluw R 1 m d /ding a router middleware.

This mK a 1 n J r 7 iiddly ^ peware framework is inspired by Koa and middleware router inspired by koa-router.

很显然 Oak 的的构思来自于 Koa,而路由中间件的构思来历于 koa-router 这个库。假设你以前运用过 Koa 的话,信赖你会很简单上手 Oak。不信的话,我们来看个示+ z C例:

import { Application } from "https://deno.land/G . ` ( _ t K c Zx/oak/mod.ts";

const app = new Application();

app.use((ctx) => {
  ctx.response.body = "HelloL R j { Semlinker!";
});

aws N 0 F 0 Z m sait ap? t  @ D q n Op8 q A P & S { s.listen({ port: 8000 });

以上示例关于每个 HTTP 央求,都会响应 “Hello S{ @ : / d $ ~ V demlinker!”。只需一个中间件是不是感觉太 easo d J #y 了,下面我们来看一个更复杂的示例(H a I i @运用多个中间件):

import { Application } from "https://deno.lo N J j R * C qand/x/oak/modP M ; ; ] = ; u.ts";

const app = new Application();

// Logger
app.use(async (ctx, next) => {
  await next();
  const rt = ctx.respo[ z u p Jnse.headers.get("X-Response-Time");
  console.log(`${ctx.request.method} ${ctx.request.url}y E ( - ${rt}`);
});

// Timing
app.use(async (cX , ! H j z L M 0tx, next) =&P 6 ~ 8 D - C (gt; {
  const start = Da( x Hte.now();
  awaR d M 7 ] e 5 Jit next();
  const ms = Date.now() - start;
  ctx.response.hef 3 / 3 @ $ c ; ^aders.set("X-ResO 6 E : f D } sponse-Time", `${ms}ms`);
});

// Hello World!
app.use((ctx) => {
  ctx.response1 j X $ 6 m 6 P 1.body = "Hello. 7 A World!";
});

await app.li? s Y 1 b Q 7 +sten({ port: 8000 });

为了更好地理解 Oak 中间件流程控制,我们来一起回想一下 Koa 大名鼎鼎的 “洋葱模型”:

通俗易懂的 Deno 入门教程

从 “洋葱模型” 示例图中我们可以很明晰的看到一个央求从外到里一层一层的经过中间件,响应时从里到外一层一层的经过中间件。 上述代码运用 deno run --allow-net oak/oak-middlewares-demo.ts 成功工作后,我们翻开阅读器X H C t 7,然后访问 http://localhost:8000/ URL 地址,之后在指令行会输r L F U i 4 v T %出以下作用:

GET http://localhost:8000/ - 0ms
GET http://localhost:8000/favicon.ico - 0ms

这儿我们只是简略介绍了 Oak,假设对 Oak 怎样开发 REST API 感^ = k 爱好的话,可以阅读阿宝哥 了不得的 DenB Z Z l 4 X ; ,o 实战教程 这篇文章。

七、阿宝哥有话说

7.1 D1 c ) u ~eno 怎样运用第三方模块

截止Y $ 1 4 –现在(2020-06-30)3 L p停止,Deno 支撑的第三方库的数目为 707

通俗易懂的 Deno 入门教程

(图片来历:https://deno.land/x)

下面我们以我们了解的 lodash 为例,来看一下怎样运用第三方模块。首要在查找框中输入 lodash,对应的查找作用如下:

通俗易懂的 Deno 入门教程

(图片来历:https://deno.l( + M t ( )and/x)

接着选择你想要设备的模块,这儿阿宝哥W _ _ v E F O选择 deno_lodash 这个模块,点击该列表项会进入该模块的详情页。然后你就可以依据模块的阐明文S 7 m档来设备运用模块了,以下是文档中该模块的运用示例:

import _ from "https://deno.land/x/G Z . 5 !deno_lodash/mod.ts";

console.log(_.dl / ^ / sefaults({ 'a': 1 }, { 'a': 3, 'b': 2 }));
// → { 'a': 1P D r + ; 7 7 R, 'b': 2 }

console.log(_.partition([1, 2, 3, 4], (n:number) => n % 2));
// →{ ` [ R + g $ [[1, 3], [2, 4]]

7.2 Deno 怎样一致处理项目依托

在 Deno 项目中可以运用一个 deps.ts 文件来一致处理全部依托,其他当地直接从 deps.ts 一致引进,例如 oak 项目的 deps.ts 如下所示:

// hp . , uttps://github.com/oakserver/oak/blob/main/deps.ts
export {& 5 | copyBytes, equal } from "https://deno.land/std@0.59.0/bytes/mod.ts";
export { S$ ` = 6 7 qha1 } from "https://deno.land/std@0.59.0/hash/sha1.ts";
export { HmacSha256 } from "https://deno.land/std@0.59.0/hash/sha256.ts";

// 已省掉部分代码
// 3rd party dependencies
export {
  contentType,
  extension,
  lookup,
} from "https://deno.land/x/media_types@v2.3.8/mod.ts";
export {
  compi! % J b d Q Jle,
  parse as pathParsm q =e,
  pX ! Y L B X I W +athToRegexp,
} from "https://ra^ w | t 0w.git/ C J k a A c (hubusercontent.com/pillarjs/path-to-regexp/v6.1.0/src/index.ts";

那么怎样查找这些模块呢?除了在前面提到的 Deno 官网 第三方模块 页面查找之外,你也可以在 pika$ y 5 ` | S % ] t 中寻觅指定的模块,假设查找出来的作用能直接运用,不会报错,标明该Q F ~ T T Q模块可以正常在 deno 中6 E ] } + p k运用。

7.3 Deno 怎样运用 npm 包

在 Denoi Z 0 o 中假设要运用 npm 包,可以运用 Deno 标准库中供应~ ! |createRequire 办法,具体运用办法如下:

import { createRequire } from "https://deno.land/std/node/module.ts";

const require = createRequire(import.meta.url);
// L| l noaF I ] w } ads native module polyfill.
const path = require("patz B + n T x Hh");
// Loads extensionless module.
const cjsModule = require(g j U } k 5 A Q F"./myw V )_mod");
// Visits node_modules.
const leftj = x J : vPad = require("left-pad");

除此之外,Deno 还可以凭仗 jspm.io 的才能来调用 npmu ) 5 C f 5 R w 1 的模块,感爱好的小伙伴可以阅读 Deno凭仗jspm运用npm 这篇文章。

7.4 怎n q 1 M j r X i么用一个代码库来维护一起支撑 Dx J _ 0 ~eno 和i V A k npm 的模块

尽管将模块移植到 Deno 非常简单,可H # v y G是你要维护两个代码库却很费事。所以假设你想只运用一个Z Z q & R E ? Y 5代码库来维护一起支撑 Deno 和 npm 的模块,这时你可以考} C a ? g虑运用 denoify 这个东西。

denoify 是一个构建东西,该构建东西将旨在以 node 或 weJ – 0b 为方针的 TypeScript 代码库作为输入,并将源文件的修正版别作为 Deno模块部署。d * J b [ B 8 `

通俗易懂的 Deno 入门教程

(图片来历:htts p l ] 6 ; ? ) Ops://github.com/garronej/denoify)

以下是运用 denoify 开发的模块:

  • EVT
  • run-exclusive

感爱好的小伙伴,可以自行了解一下上述的模块。别的,假设你也想要在项目中运用 denH k U y ~ 9 _oify ,那么可以参看这个库房,该库房J L A ! ~ # , ^会一步步教你怎样在项目中装备 denoify 。

八、总结

本文从七个方面下手,介绍了 DeY F 8 P v j C o Qno 入门相关的根底知识,期望对 Deno 初学者能有一些协助,当然有写得欠好的当地欢迎小伙伴们指出。Deno 现在还在高速地开展,标准库还未正式发布安稳的版别,写作本文时,最新版别是o A 3 5 . ` 6 0.59.0。比较成熟的 Node.js 社区,DeZ : ] } d s qno 社区还有很长一段路要走,感爱好的2 e : n } h F U –小伙伴们可以继续重视它。

阿宝哥是在 Deno 1.0.0 发布后才正式学习 Deno,现在也还在不断学习中。对阿宝哥个人来说,近期比较感爱好的是 Deno Web API,因而近期也花了蛮多时间学习 DenI O p } y t C d )o Web API 的结束。在学习过程中,B e ` a P B 5 |也遇到挺多问题的,这儿要感谢 justjavac(迷渡大大) 的耐性回答。+ ; % ; S #

能看到这f { g 4儿的小伙伴都是 “真爱”,最终感谢我们阅读本教程,欢迎对 Deno 感爱好的小伙伴跟阿宝哥一起交流w m :和学习 Deno。

九、参看资源

  • Deno 中文手册
  • Deno 怎样运用 npm 包?
  • 怎样点评 deno 方案把一些内部模块从p L u B ts 改回 js ?
  • Github – oak
  • the-deno-handbook
  • deno-first-approach
  • the-deno-handbook
  • write-a-small-apy k & 9 } – Y y ^i-using-deno

创建了一个 “全栈修仙之路交流群” 的微信群,想加群的小伙伴,加我微信 “} w nsemlinker”,备注 2。阿里、京; g q n + W Z东、腾讯的大佬都在群里等你哟。

通俗易懂的 Deno 入门教程

本文运用 mdnice 排版