node deno_Deno手册:带有代码示例的TypeScript运行时教程

node deno

I explore new projects every week, and it’s rare that one grabs my attention as much as Deno did.

我每周都会探索新的项目,很少有人像Deno那样吸引我的注意力。

In this post I want to get you up to speed with Deno quickly. We'll compare it with Node.js, and build your first REST API with it.

在这篇文章中,我想让您快速了解Deno。 我们将其与Node.js进行比较,并以此构建您的第一个REST API。

目录 (Table of contents)

And note: You can get a PDF/ePub/Mobi version of this Deno Handbook here.

请注意: 您可以在此处获取此Deno手册的PDF / ePub / Mobi版本

什么是德诺? (What is Deno?)

If you are familiar with Node.js, the popular server-side JavaScript ecosystem, then Deno is just like Node. Except deeply improved in many ways.

如果您熟悉流行的服务器端JavaScript生态系统Node.js,那么Deno就像Node。 除了在很多方面都得到了深深的改善。

Let’s start from a quick list of the features I like the most about Deno:

让我们从我最喜欢的Deno快速功能列表开始:

  • It is based on modern features of the JavaScript language

    它基于JavaScript语言的现代功能
  • It has an extensive standard library

    它具有广泛的标准库
  • It has TypeScript at its core, which brings a huge advantage in many different ways, including a first-class TypeScript support (you don’t have to separately compile TypeScript, it’s automatically done by Deno)

    它以TypeScript为核心,以许多不同的方式带来了巨大的优势,包括一流的TypeScript支持(您不必单独编译TypeScript,它由Deno自动完成)
  • It embraces ES modules

    它包含ES模块

  • It has no package manager

    它没有包管理器
  • It has a first-class await

    它有一流的await

  • It has a built-in testing facility

    它具有内置的测试设施
  • It aims to be browser-compatible as much as it can, for example by providing a built-in fetch and the global window object

    它旨在尽可能地与浏览器兼容,例如,通过提供内置的fetch和全局window对象

We’ll explore all of those features in this guide.

我们将在本指南中探索所有这些功能。

After you use Deno and learn to appreciate its features, Node.js will look like something old.

在使用Deno并了解了其功能之后,Node.js看起来会很

Especially because the Node.js API is callback-based, as it was written way before promises and async/await. There’s no change available for that in Node, because such a change would be monumental. So we’re stuck with callbacks or with promisifying API calls.

特别是因为Node.js API是基于回调的,因此它是在promise和async / await之前编写的。 Node中没有可用的更改,因为这样的更改将是巨大的。 因此,我们陷入了回调或大量API调用的困境。

Node.js is awesome and will continue to be the de facto standard in the JavaScript world. But I think we’ll gradually see Deno get adopted more and more because of its first-class TypeScript support and modern standard library.

Node.js 非常棒 ,并将继续成为JavaScript世界中的事实上的标准。 但是我认为我们将逐渐看到Deno由于其一流的TypeScript支持和现代标准库而越来越被采用。

Deno can afford to have everything written with modern technologies, since there’s no backward compatibility to maintain. Of course there’s no guarantee that in a decade the same will happen to Deno and a new technology will emerge, but this is the reality at the moment.

由于没有向后兼容性,因此Deno可以用现代技术编写所有内容。 当然,我们无法保证十年之内Deno也会发生同样的事情,并且会出现一项新技术,但这是目前的现实。

为什么是德诺? 为什么现在? (Why Deno? Why now?)

Deno was announced almost 2 years ago by the original creator of Node.js, Ryan Dahl, at JSConf EU. Watch the YouTube video of the talk, it’s very interesting and it’s a mandatory watch if you are involved in Node.js and JavaScript in general.

大约2年前,Node.js的原始创建者Ryan Dahl在JSConf EU上宣布了Deno。 观看YouTube演讲视频 ,这非常有趣,如果您通常参与Node.js和JavaScript,那么这是必看的。

Every project manager must make decisions. Ryan regretted some early decisions in Node. Also, technology evolves, and today JavaScript is a totally different language than what it was back in 2009 when Node started. Think about the modern ES6/2016/2017 features, and so on.

每个项目经理都必须做出决定。 Ryan对Node中的一些早期决定感到遗憾。 此外,技术也在不断发展,如今JavaScript与2009年Node创立时的语言已经完全不同。 考虑一下现代的ES6 / 2016/2017功能,等等。

So he started a new project to create some sort of second wave of JavaScript-powered server side apps.

因此,他开始了一个新项目,以创建第二波基于JavaScript的服务器端应用程序。

The reason I am writing this guide now and not back then is because technologies need a lot of time to mature. And we have finally reached Deno 1.0 (1.0 should be released on May 13, 2020), the first release of Deno officially declared stable.

我现在而不是那时写本指南的原因是,技术需要大量时间才能成熟。 我们终于达到了Deno 1.0 (1.0应该在2020年5月13日发布),这是Deno的第一个正式宣布稳定的版本。

That’s might seem to be just a number, but 1.0 means there will not be major breaking changes until Deno 2.0. This is a big deal when you dive into a new technology - you don’t want to learn something and then have it change too fast.

这似乎只是一个数字,但是1.0意味着直到Deno 2.0才不会有重大的重大变化。 当您深入研究新技术时,这很重要-您不想学习某些东西,然后让它改变得太快。

您应该学习Deno吗? (Should you learn Deno?)

That’s a big question.

这是一个大问题。

Learning something new such as Deno is a big effort. My suggestion is that if you are starting out now with server-side JS and you don’t know Node yet, and have never written any TypeScript, I’d start with Node.

学习诸如Deno之类的新东西是一项巨大的努力。 我的建议是,如果您现在开始使用服务器端JS,并且您还不了解Node,并且从未编写过任何TypeScript,那么我将从Node开始。

No one was ever fired for choosing Node.js (paraphrasing a common quote).

没有人因为选择Node.js而被解雇(用一个共同的说法解释)。

But if you love TypeScript, don’t depend on a gazillion npm packages in your projects and you want to use await anywhere, hey Deno might be what you’re looking for.

但是,如果您喜欢TypeScript,则不要依赖项目中庞大的npm软件包,而想要await任何地方使用await ,那么Deno可能就是您想要的。

它将取代Node.js吗? (Will it replace Node.js?)

No. Node.js is a giant, well established, incredibly well-supported technology that is going to stay around for decades.

不会。Node.js是一项庞大的,完善的,获得了难以置信的良好支持的技术,它将持续数十年。

一流的TypeScript支持 (First-class TypeScript support)

Deno is written in Rust and TypeScript, two of the languages that are really growing fast today.

Deno用Rust和TypeScript编写,这两种语言今天正在Swift发展。

In particular, being written in TypeScript means we get a lot of the benefits of TypeScript even if we might choose to write our code in plain JavaScript.

特别是,使用TypeScript编写意味着即使我们可能选择使用纯JavaScript编写代码,我们也可以获得TypeScript的很多好处。

And running TypeScript code with Deno does not require a compilation step - Deno does that automatically for you.

使用Deno运行TypeScript代码不需要编译步骤-Deno会自动为您完成此步骤。

You are not forced to write in TypeScript, but the fact the core of Deno is written in TypeScript is huge.

您没有被迫使用TypeScript编写代码,但是Deno的核心是用TypeScript编写的事实是巨大的。

First, an increasingly large percentage of JavaScript programmers love TypeScript.

首先,越来越多JavaScript程序员喜欢TypeScript。

Second, the tools you use can infer many information about software written in TypeScript, like Deno.

其次,您使用的工具可以推断出许多有关用TypeScript编写的软件的信息,例如Deno。

This means that when we code in VS Code, for example (which of course has a tight integration with TypeScript since both are developed at MicroSoft), we can get benefits like type checking as we write our code, and advanced IntelliSense features. In other words the editor can help us in a deeply useful way.

这意味着,例如,当我们使用VS Code进行编码时(由于两者都是在MicroSoft上开发的,因此与TypeScript紧密集成),我们可以在编写代码时获得类型检查和高级IntelliSense功能等好处。 换句话说,编辑器可以以非常有用的方式帮助我们。

与Node.js的异同 (Similarities and differences with Node.js)

Since Deno is basically a Node.js replacement, it’s useful to compare the two directly.

由于Deno基本上是Node.js的替代品,因此直接比较两者非常有用。

Similarities:

相似之处:

Differences:

差异:

  • Node is written in C++ and JavaScript. Deno is written in Rust and TypeScript.

    Node用C ++和JavaScript编写。 Deno用Rust和TypeScript编写。
  • Node has an official package manager called npm. Deno does not, and instead lets you import any ES Module from URLs.

    Node有一个名为npm的官方软件包管理器。 Deno不会,而是让您从URL导入任何ES模块。

  • Node uses the CommonJS syntax for importing pacakges. Deno uses ES Modules, the official way.

    Node使用CommonJS语法导入pacakges。 Deno使用官方的ES模块。
  • Deno uses modern ECMAScript features in all its API and standard library, while Node.js uses a callbacks-based standard library and has no plans to upgrade it.

    Deno在其所有API和标准库中都使用了现代ECMAScript功能,而Node.js使用了基于回调的标准库,并且没有计划对其进行升级。
  • Deno offers a sandbox security layer through permissions. A program can only access the permissions set to the executable as flags by the user. A Node.js program can access anything the user can access.

    Deno通过权限提供了一个沙箱安全层。 程序只能访问由用户设置为可执行文件的权限作为标志。 Node.js程序可以访问用户可以访问的任何内容。
  • Deno has for a long time envisioned the possibility of compiling a program into an executable that you can run without external dependencies, like Go, but it’s still not a thing yet. That’d be a game changer.

    Deno长期以来一直在考虑将程序编译为可执行文件的可能性,而该可执行文件可以在没有外部依赖项的情况下运行,例如Go,但这还不是一件容易的事 。 那将改变游戏规则。

没有包裹经理 (No package manager)

Having no package manager and having to rely on URLs to host and import packages has pros and cons. I really like the pros: it’s very flexible, and we can create packages without publishing them on a repository like npm.

没有程序包管理器并且必须依靠URL来承载和导入程序包是有利有弊。 我真的很喜欢专家:它非常灵活,我们可以创建软件包而无需在npm这样的存储库中发布它们。

I think that some sort of package manager will emerge, but nothing official is out yet.

我认为某种软件包管理器将会出现,但是还没有官方的消息。

The Deno website provides code hosting (and thus distribution through URLs) to 3rd party packages: https://deno.land/x/

Deno网站为第三方软件包提供代码托管(并因此通过URL分发): https : //deno.land/x/

安装Deno (Install Deno)

Enough talk! Let’s install Deno.

聊够了! 让我们安装Deno。

The easiest way is to use Homebrew:

最简单的方法是使用Homebrew

brew install deno

Once this is done, you will have access to the deno command. Here’s the help that you can get using deno --help:

完成此操作后,您将可以访问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命令 (The Deno commands)

Note the SUBCOMMANDS section in the help, that lists all the commands we can run. What subcommands do we have?

请注意帮助中的“ SUBCOMMANDS部分,其中列出了我们可以运行的所有命令。 我们有哪些子命令?

  • bundle bundle module and dependencies of a project into single file

    bundle束模块和项目的依赖关系到单个文件

  • cache cache the dependencies

    cache依赖项

  • completions generate shell completions

    completions生成壳补全

  • doc show documentation for a module

    doc显示模块的文档

  • eval to evaluate a piece of code, e.g. deno eval "console.log(1 + 2)"

    eval评估一段代码,例如deno eval "console.log(1 + 2)"

  • fmt a built-in code formatter (similar to gofmt in Go)

    fmt内置的代码格式化程序(类似于Go中的gofmt )

  • help prints this message or the help of the given subcommand(s)

    help打印此消息或给定子命令的帮助

  • info show info about cache or info related to source file

    info显示有关缓存的信息或与源文件相关的信息

  • install install script as an executable

    install安装脚本安装为可执行文件

  • repl Read-Eval-Print-Loop (the default)

    repl Read-Eval-Print-Loop(默认值)

  • run run a program given a filename or url to the module

    run给模块指定文件名或URL的程序

  • test run tests

    test运行测试

  • types print runtime TypeScript declarations

    types打印运行时TypeScript声明

  • upgrade upgrade deno to the newest version

    upgrade升级deno到最新版本

You can run deno <subcommand> help to get specific additional documentation for the command, for example deno run --help.

您可以运行deno <subcommand> help来获取该命令的特定其他文档,例如deno run --help

As the help says, we can use this command to start a REPL (Read-Execute-Print-Loop) using deno without any other option.

如帮助所述,我们可以使用此命令使用deno来启动REPL(Read-Execute-Print-Loop),而无需任何其他选择。

This is the same as running deno repl.

这与运行deno repl相同。

A more common way you’ll use this command is to execute a Deno app contained in a TypeScript file.

您将使用此命令的更常见方式是执行TypeScript文件中包含的Deno应用程序。

You can run both TypeScript (.ts) files, or JavaScript (.js) files.

您可以同时运行TypeScript( .ts )文件或JavaScript( .js )文件。

If you are unfamiliar with TypeScript, don’t worry: Deno is written in TypeScript, buf you can write your “client” applications in JavaScript.

如果您不熟悉TypeScript,请不要担心:Deno是用TypeScript编写的,但是您可以使用JavaScript编写“客户端”应用程序。

My TypeScript tutorial will help you get up and running quickly with TypeScript if you want.

如果需要,我的TypeScript教程将帮助您快速入门并使用TypeScript。

您的第一个Deno应用 (Your first Deno app)

Let’s run a Deno app for the first time.

让我们第一次运行Deno应用程序。

What I find pretty amazing is that you don’t even have to write a single line - you can run a command from any URL.

我感到非常惊奇的是,您甚至不必写一行-您可以从任何URL运行命令。

Deno downloads the program, compiles it and then runs it:

Deno下载程序,对其进行编译,然后运行:

Of course running arbitrary code from the Internet is not a practice I'd generally recommend. In this case we are running it from the Deno official site, plus Deno has a sandbox that prevents programs to do anything you don’t want to allow. More on this later.

当然,我一般不建议 从Internet运行任意代码 在这种情况下,我们从Deno官方站点运行它,另外Deno还有一个沙箱,可以阻止程序执行您不希望做的任何事情。 稍后再详细介绍。

This program is very simple, just a console.log() call:

该程序非常简单,只需进行console.log()调用即可:

console.log('Welcome to Deno 🦕')

If you open the https://deno.land/std/examples/welcome.ts URL with the browser, you’ll see this page:

如果使用浏览器打开https://deno.land/std/examples/welcome.ts URL,则会看到以下页面:

Weird, right? You’d probably expect a TypeScript file, but instead we have a web page. The reason is the Web server of the Deno website knows you’re using a browser and serves you a more user friendly page.

奇怪吧? 您可能希望使用TypeScript文件,但是我们有一个网页。 原因是Deno网站的Web服务器知道您正在使用浏览器,并为您提供了更加用户友好的页面。

Download the same UR using wget for example, which requests the text/plain version of it instead of text/html:

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

If you want to run the program again, it’s now cached by Deno and it does not need to download it again:

如果您想再次运行该程序,现在它由Deno缓存,不需要再次下载:

You can force a reload of the original source with the --reload flag:

您可以使用--reload标志强制重新加载原始源:

deno run has lots of different options that were not listed in the deno --help. Instead, you need to run deno run --help to reveal them:

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 code examples)

In addition to the one we ran above, the Deno website provides some other examples you can check out: https://deno.land/std/examples/.

除了上面运行的示例之外,Deno网站还提供了一些其他示例,您可以查看以下示例: https : //deno.land/std/examples/

At the time of writing we can find:

在撰写本文时,我们可以找到:

  • cat.ts prints the content a list of files provided as arguments

    cat.ts将内容打印为作为参数提供的文件列表

  • catj.ts prints the content a list of files provided as arguments

    catj.ts将内容打印为作为参数提供的文件列表

  • chat/ an implementation of a chat

    chat/的实现

  • colors.ts an example of

    colors.ts的示例

  • curl.ts a simple implementation of curl that prints the content of the URL specified as argument

    curl.ts一个简单实现的curl ,打印URL的内容指定为参数

  • echo_server.ts a TCP echo server

    echo_server.ts TCP回显服务器

  • gist.ts a program to post files to gist.github.com

    gist.ts一个将文件发布到gist.github.com的程序

  • test.ts a sample test suite

    test.ts示例测试套件

  • welcome.ts a simple console.log statement (the first program we ran above)

    welcome.ts一个简单的console.log语句(我们在上面运行的第一个程序)

  • xeval.ts allows you to run any TypeScript code for any line of standard input received. Once known as deno xeval but since removed from the official command.

    xeval.ts允许您为收到的标准输入的任何行运行任何TypeScript代码。 曾经称为deno xeval但此后从官方命令中删除。

您的第一个Deno应用程序(真实) (Your first Deno app (for real))

Let’s write some code.

让我们写一些代码。

Your first Deno app you ran using deno run https://deno.land/std/examples/welcome.ts was an app that someone else wrote, so you didn’t see anything in regards to how Deno code looks like.

您使用deno run https://deno.land/std/examples/welcome.ts第一个Deno应用程序deno run https://deno.land/std/examples/welcome.ts是其他人编写的应用程序,因此您对Deno代码的外观一无所知。

We’ll start from the default example app listed on the Deno official website:

我们将从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' })
}

This code imports the serve function from the http/server module. See? We don’t have to install it first, and it’s also not stored on your local machine like it happens with Node modules. This is one reason why the Deno installation was so fast.

此代码从http/server模块导入serve函数。 看到? 我们不必先安装它,也不会像Node模块那样将其存储在本地计算机上。 这是Deno安装如此之快的原因之一。

Importing from https://deno.land/std/http/server.ts imports the latest version of the module. You can import a specific version using @VERSION, like this:

https://deno.land/std/http/server.ts导入会导入模块的最新版本。 您可以使用@VERSION导入特定版本,如下所示:

import { serve } from 'https://deno.land/std@v0.42.0/http/server.ts'

The serve function is defined like this in this file:

在此文件中, 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)
}

We proceed to instantiate a server calling the serve() function passing an object with the port property.

我们继续实例化一个调用serve()函数的服务器,该服务器传递带有port属性的对象。

Then we run this loop to respond to every request coming from the server.

然后,我们运行此循环以响应来自服务器的每个请求。

for await (const req of s) {
  req.respond({ body: 'Hello World\n' })
}

Note that we use the await keyword without having to wrap it into an async function because Deno implements top-level await.

请注意,我们使用await关键字而不必将其包装到async函数中,因为Deno实现了顶级await

Let’s run this program locally. I assume you use VS Code, but you can use any editor you like.

让我们在本地运行该程序。 我假设您使用VS Code ,但是您可以使用任何喜欢的编辑器。

I recommend installing the Deno extension from justjavac (there was another one with the same name when I tried, but deprecated - might disappear in the future)

我建议从justjavac安装justjavac扩展名(我尝试时有另一个同名,但已弃用-将来可能会消失)

The extension will provide several utilities and nice thing to VS Code to help you write your apps.

该扩展将为VS Code提供一些实用工具和好东西,以帮助您编写应用。

Now create an app.ts file in a folder and paste the above code:

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

Now run it using deno run app.ts:

现在使用deno run app.ts运行它:

Deno downloads all the dependencies it needs, by first downloading the one we imported.

通过首先下载我们导入的依赖,Deno会下载所需的所有依赖项。

The https://deno.land/std/http/server.ts file has several dependencies on its own:

https://deno.land/std/http/server.ts文件本身具有多个依赖项:

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

and those are imported automatically.

那些是自动导入的。

At the end though we have a problem:

最后,尽管我们有一个问题:

What is happening? We have a permission denied problem.

怎么了? 我们有一个权限被拒绝的问题。

Let’s talk about the sandbox.

让我们谈谈沙盒。

Deno沙箱 (The Deno sandbox)

I mentioned previously that Deno has a sandbox that prevents programs from doing anything you don’t want to allow.

我之前提到过,Deno有一个沙箱,可以防止程序执行您不希望做的任何事情。

What does this mean?

这是什么意思?

One of the things that Ryan mentions in the Deno introduction talk is that sometimes you want to run a JavaScript program outside of the Web Browser, and yet do not want allow it to access to anything it wants on your system. Or talk to the external world using a network.

Ryan在Deno简介演讲中提到的一件事是,有时您想在Web浏览器之外运行JavaScript程序,但又不想让它访问系统上想要的任何东西。 或使用网络与外界对话。

There’s nothing stopping a Node.js app from getting your SSH keys or any other thing on your system and sending it to a server. This is why we usually only install Node packages from trusted sources. But how can we know if one of the projects we use gets hacked and in turn everyone else does?

没有什么可以阻止Node.js应用程序获取您的SSH密钥或系统上的任何其他东西并将其发送到服务器的。 这就是为什么我们通常只从受信任的源安装Node软件包。 但是,我们如何知道我们使用的一个项目是否遭到黑客入侵,而其他所有人又被黑客入侵呢?

Deno tries to replicate the same permission model that the browser implements. No JavaScript running in the browser can do shady things on your system unless you explicitly allow it.

Deno尝试复制浏览器实现的相同权限模型。 除非您明确允许,否则在浏览器中运行JavaScript不会在您的系统上做任何可疑的事情。

Going back to Deno, if a program want to access the network like in the previous case, then we need to give it permission.

回到Deno,如果程序想要像以前的情况一样访问网络,那么我们需要给它权限。

We can do so by passing a flag when we run the command, in this case --allow-net:

我们可以通过在运行命令时传递一个标志来实现,在本例中为--allow-net

deno run --allow-net app.ts

The app is now running an HTTP server on port 8000:

该应用程序现在在端口8000上运行HTTP服务器:

Other flags allow Deno to unlock other functionality:

其他标志允许Deno解锁其他功能:

  • --allow-env allow environment access

    --allow-env允许环境访问

  • --allow-hrtime allow high resolution time measurement

    --allow-hrtime允许高分辨率时间测量

  • --allow-net=<allow-net> allow network access

    --allow-net=<allow-net>允许网络访问

  • --allow-plugin allow loading plugins

    --allow-plugin允许加载插件

  • --allow-read=<allow-read> allow file system read access

    --allow-read=<allow-read>允许文件系统读取访问

  • --allow-run allow running subprocesses

    --allow-run允许运行子进程

  • --allow-write=<allow-write> allow file system write access

    --allow-write=<allow-write>允许文件系统写访问

  • --allow-all allow all permissions (same as -A)

    --allow-all允许所有权限(与-A相同)

Permissions for net, read and write can be granular. For example, you can allow reading from a specific folder using --allow-read=/dev

netreadwrite权限可以是细粒度的。 例如,您可以使用--allow-read=/dev允许从特定文件夹中--allow-read=/dev

格式化代码 (Formatting code)

One of the things I really liked from Go was the gofmt command that came with the Go compiler. All Go code looks the same. Everyone uses gofmt.

我真正喜欢Go的一gofmt是Go编译器随附的gofmt命令。 所有Go代码看起来都一样。 每个人都使用gofmt

JavaScript programmers are used to running Prettier, and deno fmt actually runs that under the hood.

JavaScript程序员用来运行更漂亮 ,和deno fmt实际运行的引擎盖下。

Say you have a file formatted badly like this:

假设您有一个格式严重错误的文件,如下所示:

You run deno fmt app.ts and it’s automatically formatted properly, also adding semicolons where missing:

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

标准库 (The standard library)

The Deno standard library is extensive despite the project being very young.

尽管该项目还很年轻,但Deno标准库仍然很庞大。

It includes:

这包括:

  • archive tar archive utilities

    archive tar存档实用程序

  • async async utilties

    async异步工具类

  • bytes helpers to manipulate bytes slices

    bytes助手来操纵字节片

  • datetime date/time parsing

    datetime日期/时间解析

  • encoding encoding/decoding for various formats

    encoding各种格式的编码/解码

  • flags parse command-line flags

    flags解析命令行标志

  • fmt formatting and printing

    fmt格式化和打印

  • fs file system API

    fs文件系统API

  • hash crypto lib

    hash加密库

  • http HTTP server

    http HTTP服务器

  • io I/O lib

    io输入/输出库

  • log logging utilities

    log记录实用程序

  • mime support for multipart data

    mime支持多部分数据

  • node Node.js compatibility layer

    node Node.js兼容性层

  • path path manipulation

    path路径操作

  • ws websockets

    ws websockets

另一个Deno示例 (Another Deno example)

Let’s see another example of a Deno app, from the Deno examples: cat:

让我们从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()
}

This assigns to the filenames variable the content of Deno.args, which is a variable containing all the arguments sent to the command.

这会将Deno.args的内容分配给filenames变量,该变量是包含发送到命令的所有参数的变量。

We iterate through them, and for each we use Deno.open() to open the file and we use Deno.copy() to print the content of the file to Deno.stdout. Finally we close the file.

我们遍历它们,并且对于每一个我们都使用Deno.open()打开文件,然后使用Deno.copy()将文件的内容打印到Deno.stdout 。 最后,我们关闭文件。

If you run this using

如果您使用

deno run https://deno.land/std/examples/cat.ts

The program is downloaded and compiled, and nothing happens because we didn’t specify any argument.

该程序已下载并编译,没有任何React,因为我们未指定任何参数。

Try now

现在试试

deno run https://deno.land/std/examples/cat.ts app.ts

assuming you have app.ts from the previous project in the same folder.

假设您在同一文件夹中有上一个项目的app.ts

You’ll get a permission error:

您会收到权限错误:

Because Deno disallows access to the filesystem by default. Grant access to the current folder using --allow-read=./:

因为Deno默认情况下不允许访问文件系统。 使用--allow-read=./授予对当前文件夹的访问权限:

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

Deno是否有Express / Hapi / Koa / *? (Is there an Express/Hapi/Koa/* for Deno?)

Yes, definitely. Check out projects like

当然是。 签出类似的项目

示例:使用Oak构建REST API (Example: use Oak to build a REST API)

I want to make a simple example of how to build a REST API using Oak. Oak is interesting because it’s inspired by Koa, the popular Node.js middleware, and due to this it’s very familiar if you’ve used that before.

我想举一个简单的示例,说明如何使用Oak构建REST API。 Oak很有趣,因为它受到流行的Node.js中间件Koa的启发,因此,如果您以前使用过它,将非常熟悉。

The API we’re going to build is very simple.

我们要构建的API非常简单。

Our server will store, in memory, a list of dogs with name and age.

我们的服务器将在内存中存储带有名称和年龄的狗的列表。

We want to:

我们想:

  • add new dogs

    添加新狗
  • list dogs

    列出狗
  • get details about a specific dog

    获取有关特定狗的详细信息
  • remove a dog from the list

    从名单上删除一只狗
  • update a dog's age

    更新狗的年龄

We’ll do this in TypeScript, but nothing stops you from writing the API in JavaScript - you simply remove the types.

我们将在TypeScript中进行此操作,但是没有什么可以阻止您使用JavaScript编写API-您只需删除类型。

Create a app.ts file.

创建一个app.ts文件。

Let’s start by importing the Application and Router objects from Oak:

让我们首先从Oak导入ApplicationRouter对象:

import { Application, Router } from 'https://deno.land/x/oak/mod.ts'

then we get the environment variables PORT and HOST:

然后我们得到环境变量PORT和HOST:

const env = Deno.env.toObject()
const PORT = env.PORT || 4000
const HOST = env.HOST || '127.0.0.1'

By default our app will run on localhost:4000.

默认情况下,我们的应用程序将在localhost:4000上运行。

Now we create the Oak application and we start it:

现在,我们创建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}`)

Now the app should be compiling fine.

现在,应用程序应该可以正常编译了。

Run

deno run --allow-env --allow-net app.ts

and Deno will download the dependencies:

然后Deno将下载依赖项:

and then listen on port 4000.

然后在端口4000上侦听。

The next times you run the command, Deno will skip the installation part because those packages are already cached:

下次运行命令时,Deno将跳过安装部分,因为这些软件包已被缓存:

At the top of the file, let’s define an interface for a dog, then we declare an initial dogs array of Dog objects:

在文件的顶部,让我们为狗定义一个接口,然后声明一个Dog对象的初始dogs数组:

interface Dog {
  name: string
  age: number
}

let dogs: Array<Dog> = [
  {
    name: 'Roger',
    age: 8,
  },
  {
    name: 'Syd',
    age: 7,
  },
]

Now let’s actually implement the API.

现在,让我们实际实现API。

We have everything in place. After you create the router, let’s add some functions that will be invoked any time one of those endpoints is hit:

我们已经准备就绪。 创建路由器后,让我们添加一些在命中这些端点之一时将被调用的功能:

const router = new Router()

router
  .get('/dogs', getDogs)
  .get('/dogs/:name', getDog)
  .post('/dogs', addDog)
  .put('/dogs/:name', updateDog)
  .delete('/dogs/:name', removeDog)

See? We define

看到? 我们定义

  • GET /dogs

    GET /dogs

  • GET /dogs/:name

    GET /dogs/:name

  • POST /dogs

    POST /dogs

  • PUT /dogs/:name

    PUT /dogs/:name

  • DELETE /dogs/:name

    DELETE /dogs/:name

Let’s implement those one-by-one.

让我们一一实现。

Starting from GET /dogs, which returns the list of all the dogs:

GET /dogs ,它返回所有狗的列表:

export const getDogs = ({ response }: { response: any }) => {
  response.body = dogs
}

Next, here’s how we can retrieve a single dog by name:

接下来,这是我们如何通过名称检索一只狗的方法:

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

Here is how we add a new 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
}

Notice that I now used const body = await request.body() to get the content of the body, since the name and age values are passed as JSON.

注意,由于nameage值作为JSON传递,我现在使用const body = await request.body()来获取正文的内容。

Here’s how we update a dog’s age:

这是我们更新狗的年龄的方法:

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

and here is how we can remove a dog from our list:

这是我们如何从列表中删除狗的方法:

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
}

Here’s the complete example code:

这是完整的示例代码:

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

了解更多 (Find out more)

The Deno official website is https://deno.land

迪诺官方网站为https://deno.land

The API documentation is available at https://doc.deno.land and https://deno.land/typedoc/index.html

该API文档位于https://doc.deno.landhttps://deno.land/typedoc/index.html

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

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

一些随机花絮 (A few more random tidbits)

  • Deno provides a built-in fetch implementation that matches the one available in the browser

    Deno提供了一个内置的fetch实现,该实现与浏览器中可用的匹配

  • Deno has a compatibility layer with the Node.js stdlib in progress

    Deno 正在进行与Node.js stdlib的兼容层

最后的话 (Final words)

I hope you enjoyed this Deno tutorial!

我希望您喜欢这个Deno教程!

Reminder: You can get a PDF/ePub/Mobi version of this Deno Handbook here.

提醒: 您可以在此处获取此Deno手册的PDF / ePub / Mobi版本

翻译自: https://www.freecodecamp.org/news/the-deno-handbook/

node deno

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值