Deno 入门指南(二)

Deno入门:Node.js的现代替代品 fetch(url)异步地发起HTTP GET请求到指定的URL。response.ok检查HTTP状态码是否在200-299之间,表示请求成功。response.text()获取响应体的文本内容。parseJson(text)将文本内容解析为JSON对象。console.log(data)打印解析后的数据。// 在其他文件中导入// 输出 5。 阅读详情

原文:Introducing Deno

协议:CC BY-NC-SA 4.0

五、现有模块

到目前为止,我们已经介绍了 Deno 引入 JavaScript 生态系统的每一个重大变化,现在是时候回顾一下您已经可以用它做的事情了。

不要误会我;你可以用它做任何你想用 Node.js 做的事情。你可能知道,NPM 有几乎同样多的用户发布的数百万个模块,虽然这些代码是 JavaScript,但它并不是 100%与 Deno 兼容,所以我们不能像 11 年前一样重复使用这些工作。

也就是说,Deno 的标准库已经很强大了,从第一天开始,就已经有用户将模块从 Node 移植到 Deno,以使它们兼容,所以我们有很多工具可以使用。

在这一章中,我将介绍其中的一些,以便向您展示虽然这个新的运行时还不到一年,但是您可以用它来做一些非常有趣的项目。

Deno 标准:标准库

让我们从安装 Deno:标准库的第一天就提供给我们的模块开始。这实际上非常重要,因为对 Ryan 来说,Node.js 有一个非常糟糕的标准库,并且缺少任何人开始做相关事情所需的大多数基本工具。作为在 2012 年左右开始在 0.10 版本上使用 Node 的人,我可以确认,在存在 3 年之后,Node.js 没有真正的标准库。它的重点是为后端开发人员提供异步 I/O,但仅此而已;整个开发人员的体验并不好,尤其是与今天的标准相比。

不过这不是问题,因为 Node 越受欢迎,就有越多的用户将他们可用的基本构建模块编译成更有用的库,并开始通过 NPM 共享。尽管 Deno 已经有了相当多的社区,并且他们开始编写新的库或者将现有的库移植到这边,但是这些数字还不能比较,至少现在还不能。

现在回到性病,因为这是我们在这里要讨论的。正如我在第一章中提到的,这种最初的功能分组部分受到了 Go 及其标准库的启发,所以如果在 Deno 的未来更新中,他们继续从那里移植更多的想法,我不会感到惊讶。但是到目前为止,Deno 的标准库包含 21 个稳定的模块,一个实验性的模块,以及一些已经可供您查看的示例。

表 5-1

Deno 标准库包含的所有模块的列表

|

组件

|

描述

|
| — | — |
| 档案馆 | 归档功能,在撰写本书时,它为您提供了归档和解压缩文件的能力。 |
| 异步ˌ非同步(asynchronous) | 处理异步行为的工具集。我不是在谈论承诺或异步/等待;这些是语言本身的一部分。这里有一些东西,比如选择代码执行延迟时间的延迟函数,或者将 resolve 和 reject 函数作为方法添加到 promise 中。 |
| 字节 | 操作字节的低级函数集。如果你不这样对待二进制对象,它们将需要更多的工作;这些功能将帮助您简化这项任务。 |
| 日期时间 | 一些辅助函数和一些字符串解析函数,帮助您在字符串和日期对象之间架起一座桥梁。 |
| 编码 | 非常有用的模块来处理外部数据结构。还记得 JSON 结构是如何获得 JSON 全局对象的吗?嗯,在这里您可以添加对 YAML,CSV 和其他几个的支持。 |
| 旗帜 | 命令行参数分析器。如果您正在构建一个 CLI 工具,就不再需要导入一个模块来完成这项工作;你已经有了。这显示了一个经过深思熟虑的标准库的威力。 |
| 滤波多音 | 文本格式化功能。如果console.log对你来说还不够,这个模块有你所需要的一切来增加你的控制台消息的活力。 |
| 满量程 | 额外文件系统功能。我们不是在谈论只是读写一个文件;这可以直接从 Deno 名称空间完成。我们正在讨论使用通配符作为路径的一部分,复制文件和文件夹,移动它们,等等。注意:在撰写本文时,这个模块被标记为不稳定,所以你需要--unstable标志来访问它。 |
| 混杂 | 该库增加了对创建和处理 10 多种用于创建散列的算法的支持。 |
| 超文本传送协议(Hyper Text Transport Protocol 的缩写) | HTTP 相关的函数。如果你试图创建一个 web 服务器(例如,在一个微服务上工作,一个单一的 web 应用,或者介于两者之间的东西),在这里你可以得到你所需要的一切。 |
| 木卫一 | 这是 Deno 处理流的模块,当然包括标准输入的模块。这意味着,如果您希望从用户那里请求输入(当然,除了其他事情之外),这就是您要使用的模块。 |
| 原木 | 这个模块是 Deno 拥有非常完整的标准库的证明。有多少次你不得不在 Node 中实现你自己的记录器?或者为你的项目寻找最好的伐木工?相反,Deno 已经有一个非常完整和灵活的供您使用,而不必出去寻找任何东西。 |
| 哑剧 | 一组专用于处理多部分表单数据的函数,包括读取和写入。 |
| 结节 | 这是一个与 Node.js 的标准库兼容的模块。它为一些最常见的节点功能(如 require 或 events)提供了聚合填充。如果你想把代码从节点移植到节点,这是一个你想回顾的模块;不然真的没什么用。 |
| 小路 | 用来处理路径的一组经典函数,例如从路径中获取文件夹名,或者提取一组不同路径的公共路径等等。 |
| 许可 | 一个小模块,用来授予你的脚本权限。它要求使用--unstable标志。它与上一章描述的Deno.permissions API 非常相似。 |
| 信号 | 提供一个 API 来处理进程信号。这是一个相当低级的 API,但它允许您处理 SIGINT 和 SIGTSTP 之类的信号。 |
| 测试 | 就像日志模块一样,这次 Deno 也为您提供了创建测试套件所需的一切。 |
| 全局唯一识别 | 以前需要创建一个唯一的 ID 吗?本模块将帮助您使用 UUID 标准支持的不同版本(1、3、4 和 5)之一创建一个。 |
| 艾德 | WebAssembly 系统接口(WASI)的实现,可用于编译 WASM 代码。 |
| 《华盛顿明星报》 | 我们在列表中遗漏了一样东西:WebSocket 支持。 |

表 5-1 对标准模块进行了快速概述;它们都在不断发展,但同时,由于它们作为 Deno 生态系统的一部分发挥着至关重要的作用,它们由核心团队直接审查。就像任何开源项目一样,您可以发送您的贡献;只要明白他们不能有任何外部依赖。

外部模块

正如我已经提到的,Deno 的用户定制模块生态系统还不能与 Node 的相比,因为它已经存在了很长时间。也就是说,机构群体正在做大量工作来弥合这一差距。

毕竟,现有的每个节点模块都是用 JavaScript 编写的,只是风格略有不同,所以翻译是可行的。这只是需要时间,尤其是当你要翻译的模块有依赖项时,因为你也必须翻译那些依赖项。

自 Deno 发布以来,已经部署了一些解决方案,以便通过某种形式的单一位置浏览和查找模块(阿拉 NPM 网站),或者通过跟踪 URL 或者直接存储所有内容。

我将快速介绍最近部署的两个主要存储库,您可以使用它们来了解已经有哪些可供您使用的存储库。

官方名单

Deno 的网站( http://deno.land )提供免费的 URL 重写服务,你可以贡献你的链接到列表中。基本上,他们会在他们的网站上列出你的模块(目前,已经有超过 700 个模块被显示)并重定向到它们。这个注册中心的数据库目前是一个 JSON 文件,您必须对其进行编辑并发送一个 Pull 请求。

就个人而言,我不认为这是非常可扩展的,所以我假设在不久的将来他们会提供另一种方式来更新列表并向其中添加您自己的模块。

但是现在,创建这个列表的方法是向这个存储库发送一个 Pull 请求: https://github.com/denoland/deno_website2 ,具体来说是对名为database.json的文件的修改,这个文件可以直接在那个 repo 的根文件夹中找到。

文件的格式见清单 5-1;如您所知,没有太多的字段可以提供,尽管没有关于它的官方文档,但您可以看到它足够简单。

{
//...
"a0": {
"type": "github",
"owner": "being-curious",
"repo": "a0",
"desc": "A command line utility to manage `text/number/email/password/address/note` with Alias to easy recall & copy to clipboard.",
"default_version": "master"
//...
}

Listing 5-1Sample section of the database.json file

在deno.land/x可以看到储存库,看起来像图 5-1;本质上,你得到一个基本的搜索框,可以过滤超过 700 个已发布的模块。

img/501657_1_En_5_Fig1_HTML.jpg

图 5-1

Deno 的官方模块库

如果您将分支机构名称作为 URL 的一部分添加,该重定向规则也会考虑到它的创建方式。如果这样做,它会向该分支发送流量;否则,它会认为你的目标是主分支。作为我在第四章中提到的使用标签的替代方法,你也可以使用分支名称作为你的版本号,由于这个有用的重定向,这也可能对你有利。有了它,你可以写一些类似 http://deno.land/x/your-module@1.4/ 的东西,这将把流量重定向到你在 GitHub 的账户(假设这是我们正在谈论的你的模块),在它里面,到那个模块的文件夹,在它里面,特定的分支称为 1.4。

最酷的是,您可以使用这个方法从代码中导入模块。记住,这只是一个重定向服务;实际的文件存储在你放的任何地方,在这种情况下,它将是 GitHub 自己的服务器。

同样,这不是集中式存储库的替代品,而仅仅是一个搜索将不断增长的分散模块海洋的伟大工具。

凭借区块链的力量

第二个,也是最有希望找到 Deno 模块的平台是 nest.land。虽然与之前的服务不同,这个平台也存储你的代码,但它没有使用常规平台,而是使用区块链网络。

这是正确的;通过使用区块链的力量,这个平台不仅为你的模块创建了一个分布式存储,而且是一个永久的存储。通过这个平台和发布你的模块,你将它们储存在 Arweave perma web1中,从技术上讲,它们将永远存在于此。所以移除模块是不可能的,这在发布模块时已经提供了比任何其他选项更大的优势,因为模块可能被意外移除的事实是依赖外部包的最大风险之一。

这个平台的缺点是它还没有前一个平台受欢迎,所以没有很多包在那里发布。图 5-2 展示了他们主页的样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-2

图库,列出已发布的模块

为了导入存储在该平台中的模块,您将从网站获得一个 URL,您可以从您的代码中使用它,它们都遵循相同的模式: https://x.nest.land/ <module-name>@<module-version>/mod.ts

例如,模块 Drash, 2 是一个 HTTP 微框架,可以使用以下 URL 导入: https://x.nest.land/deno-drash@1.0.7/mod.ts 。

另一方面,如果您希望在这个平台上发布您的模块,那么您必须安装他们的 CLI 工具(称为 egg)。为了做到这一点,您至少需要 Deno 的 1.1.0 版本,使用下面的命令,您应该能够安装它:

deno install -A -f --unstable -n eggs https://x.nest.land/eggs@0.1.8/mod.ts

请注意,您提供了所有特权(使用-A 标志),并且还通过使用--unstable标志授予了使用不稳定特性的权限。

一旦安装完毕,您就必须使用eggs link --key [your key]链接您的 API 密钥(您应该在注册后获取、下载并存储在您的本地存储中)。

通用安装说明到此结束;之后,你必须进入你的模块的文件夹,并使用egg init初始化它(就像你用npm init一样)。

在初始化过程中,您会被问到几个关于项目的问题,比如名称,如果是模块的不稳定版本的描述,要发布的文件列表,以及配置文件的格式(JSON 或 YAML)。

配置文件的格式类似于清单 5-2 中的格式。

{
    "name": "module-name",
    "description": "Your brief module description",
    "version": "0.0.1",
    "entry": "./src/main.ts",
    "stable": true,
    "unlisted": false,
    "fmt": true,
    "repository": "https://github.com/your_name/your_project",
    "files": [
        "./mod.ts",
        "./src/**/*",
        "./README.md"
    ]
}

Listing 5-2Sample configuration file for nest

尽管这看起来像是 Node 中受人喜爱的package.json的一个副本,但事实上并非如此。这个文件是简化显示信息和管理包的任务所必需的,但是它不包括额外的信息,例如依赖项列表,也不包括项目范围的配置或命令。因此,尽管它仍然添加了一个配置文件,但您并没有将所有内容都集中到一个充满不相关内容的文件中。

有了这个文件,剩下要做的就是发布你的模块,你可以用命令egg publish. A来完成,之后,你就可以在库中看到你的模块,它将永远存在(或者至少直到 permaweb 被关闭)。

要查看的有趣模块

为了结束这一章,我想介绍一些你可能感兴趣的模块,这取决于你想用 Deno 实现什么。

当然,没有什么可以阻止你使用其他模块,但至少它会给你一个起点。

API 开发

可能与后端异步 I/O 运行时相关的最常见任务之一是开发 API 或任何基于 web 的项目。这就是 Node.js 在微服务项目上获得如此多关注的原因。

对于 Deno,已经有一些非常有趣的框架可用。

德雷什

使用这个模块,您可以创建一个直接的 API 或 web 应用;您可以根据自己选择的生成器脚本来决定使用哪一个。本质上,Drash 为您提供了一个生成器脚本,让您能够创建所需的所有基本样板代码。

最酷的是,由于像 Deno 提供的远程导入和执行远程文件的能力,您可以使用生成器,而不必在您的计算机上安装任何东西。下面一行显示了您需要执行的确切命令:

$ deno run --allow-run --allow-read --allow-write --allow-net https://deno.land/x/drash/create_app.ts --api

现在,您应该能够完全理解这个命令在做什么。基本上,您正在执行create_app.ts脚本,为了确保它能够工作,您允许它运行子进程,在您的硬盘上读写,并建立网络连接,可能是为了下载所需的文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-3

执行 Drash 生成器后的项目结构

项目结构非常简单,如图 5-3 所示;注意deps.ts文件,它遵循我在第四章中介绍的相同模式。目前,它只导出两个依赖项,如您在清单 5-3 中看到的,但是您将使用这个文件导出您将来可能添加的任何其他内容。

export { Drash } from "https://deno.land/x/drash@v1.0.0/mod.ts";
export { assertEquals } from "https://deno.land/std@v0.52.0/testing/asserts.ts";

Listing 5-3Default exports added by Drash

在 resources 文件夹中,您可以看到这个框架试图使用面向对象的方法,通过扩展Drash.Http.Resource来声明资源。清单 5-4 展示了自动生成的资源,这反过来清楚地说明了用这种方法实现一个基于 REST 的 API 是多么容易。

export default class HomeResource extends Drash.Http.Resource {
  static paths = ["/"];

  public GET() {
   this.response.body = JSON.stringify(
    { success: true, message: "GET request received."    },
   );
   return this.response;
  }

  public POST() {
    this.response.body = JSON.stringify({ message: "Not implemented" });
    return this.response;
  }

  public DELETE() {
    this.response.body = JSON.stringify({ message: "Not implemented" });
    return this.response;
  }

  public PUT() {
    this.response.body = JSON.stringify({ message: "Not implemented" });
    return this.response;
  }
}

Listing 5-4Autogenerated resource class by Drash

至于它的文档,他们的网站 3 包含一组非常详细的例子,带你从最基本的用例到最复杂的用例。作为一名来自 Express 4 或 Restify、 5 等框架的开发人员,Drash 采用的方法是新鲜而有趣的,考虑到它主要侧重于 TypeScript 和我们在第二章中介绍的几个特性。

如果您希望快速完成一些工作,并使用 Deno 设置一个 API,可以考虑看看这个新的尝试,而不是使用迁移的节点模块。

数据库访问

无论您正在开发哪种应用,您都很可能需要使用数据库。无论是基于 SQL 的还是 NoSQL 的,如果你需要,Deno 都能满足你。

结构化查询语言

如果你正在考虑使用 SQL(特别是 SQLite、MySQL 或 Postgre),那么 Cotton 6 是你的首选;类似于 sequelize 7 为 Node 所做的,这个模块试图为开发者提供一个数据库无关的方法。您担心使用正确的方法,它会为您编写查询。最好的部分是,如果你需要,你也可以写你自己的原始查询,当然,这将打破 ORM 模式,但它也给你最复杂的用例所需的灵活性。

你可以直接从 Deno 的模块库中导入这个模块,换句话说,从你的代码中使用 https://deno.land/x/cotton/mod.ts 。然后使用清单 5-5 中的代码连接到数据库。

import { connect } from "https://deno.land/x/cotton/mod.ts";

const db = await connect({
  type: "sqlite", // available type: 'mysql', 'postgres', and 'sqlite'
  database: "db.sqlite",
  // other...
});

Listing 5-5Connecting to your favorite SQL database

然后,您可以通过直接编写 SQL 来查询您的表,如清单 5-6 所示,或者使用清单 5-7 所示的数据库模型(遵循 ORM 模式)。

const users = await db.query("SELECT * FROM users;");

for (const user of users) {
  console.log(user.email);
}

Listing 5-6Raw query getting the list of users

请注意,结果是如何将用户直接转换为具有正确属性的对象,而不是必须使用自定义方法来获取正确的属性,或者甚至为每个记录创建一个值数组。

import { Model } from "https://deno.land/x/cotton/mod.ts";

class User extends Model {
  static tableName = "users";

  @Field()
  email!: string;

  @Field()
  age!: number;

  @Field()
  created_at!: Date;
}
//and now query your data...
const user = await User.findOne(1); // find user by id
console.log(user instanceof User); // true

Listing 5-7Using the ORM pattern to query the database

当然,如果您想走这条路,您必须更改 TypeScript 编译器上的默认配置;不然就不行了。你可以在你的项目文件夹中有一个类似于清单 5-8 的tsconfig.json文件。

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Listing 5-8Required configuration to make decorators work

然后用下面一行执行您的代码:

$ deno run -c tsconfig.json main.ts

NoSQL

另一方面,如果您希望与 NoSQL 数据库进行交互,推荐一个模块的任务会变得有点复杂,因为由于 NoSQL 数据库的性质,您很难找到一个适用于所有数据库的模块。

相反,您必须寻找专门为您的数据库设计的东西。在这里,我将为 MongoDB 和 Redis 推荐一些东西,因为它们是两个主要的 NoSQL 数据库。

MongoDB

基于文档的数据库是 NoSQL 的经典选择,尤其是 MongoDB,考虑到它与 JavaScript 的集成,非常适合我们最喜欢的运行时。

DenoDB 8 是除 deno_mongo 9 之外为数不多的为 mongoDB 提供支持的模块,deno _ Mongo9 是用 Rust 编写的 Mongo 驱动程序之上的直接包装器。有趣的是,这个模块还支持一些主要的基于 SQL 的数据库,所以它涵盖了所有的基础知识。

连接 Mongo 很容易;您只需要确保您指定了清单 5-9 中所示的正确选项,定义您的模型就像扩展模块导出的模型类一样简单(参见清单 5-10 中的示例)。

class Flight extends Model {
  static fields = {
    _id: {
      primaryKey: true,
    },
  };
}
const flight = new Flight();
flight.departure = 'Dublin';
flight.destination = 'Paris';
flight.flightDuration = 3;
await flight.save()

Listing 5-10Using models to interact with the collections

import { Database } from 'https://deno.land/x/denodb/mod.ts';

const db = new Database('mongo', {
  uri: 'mongodb://127.0.0.1:27017',
  database: 'test',
});

Listing 5-9Connecting to Mongo

这个模块唯一的缺点是明显缺乏对原始查询的支持。因此,如果你发现自己需要模块的 API 没有给你的操作,请记住,它只是使用 deno_mongo 来处理连接,所以你可以通过getConnector方法直接访问该对象。

使用心得

Redis 是一种完全不同类型的数据库,因为它处理的是键-值对,而不是实际的类似文档的记录,所以遵循相同的基于 ORM 的方法没有什么意义。

因此,我们将使用 Deno 的 Redis 驱动程序的直接端口,可以访问所有经典的 Redis 方法。如果您来自 Node 并且以前使用过 Redis 包,这应该感觉非常相似。

import { connect } from "https://denopkg.com/keroxp/deno-redis/mod.ts";

const redis = await connect({
  hostname: "127.0.0.1",
  port: 6379
});

const ok = await redis.set("hoge", "fuga");
const fuga = await redis.get("hoge");

Listing 5-11Connecting to Redis from Deno

清单 5-11 显示了取自文档的一个基本例子,但是你可以在那里看到正在使用的set和get方法。还支持 Pub/Sub API 和一个非常有趣的特性:原始请求(参见下面的示例片段)。

await redis.executor.exec("SET", "redis", "nice"); // => ["status", "OK"]
await redis.executor.exec("GET", "redis"); // => ["bulk", "nice"]

当然,您通常希望使用 API 提供的方法,但是这允许您访问尚不属于稳定 API 的特性。仅在极端情况下使用此选项;否则,坚持使用标准方法。

Tip

为了让您的代码与这个模块一起工作,您需要使用--allow-net标志提供网络特权。

命令行界面

作为 Deno 等运行时的另一个经典用例,考虑到 JavaScript 的动态性,很容易将其用于开发工具,这就是 CLI 工具的用武之地。

尽管 Deno 作为其标准库的一部分已经提供了一个非常全面的参数解析模块,但是在创建命令行工具时还需要注意其他事情。

为此,模块 Cliffy 10 提供了一套完整的软件包,处理创建这些工具所涉及的所有方面。

作为该模块的一部分,有六个集中了不同功能的包,允许您只导入您需要的部分,而没有单一的巨大依赖。

  • ansi-escape:11允许您在需要时通过四处移动或隐藏光标来与 CLI 光标进行交互。

  • 命令:12你可以使用这个模块为你的 CLI 工具创建命令。它提供了一个非常易于使用的 API,可以自动生成帮助消息并帮助您解析 CLI 参数。

  • flags : 13 把这个模块想象成 Deno 的 flag 解析包上了类固醇。它允许您为您的标志提供一个非常详细的模式,指定诸如别名、它们是否是强制的、与其他标志的依赖性等等。它帮助您将 CLI 工具从基础版本升级为经过充分思考和专业设计的工具。

  • keycode:14如果你试图请求用户输入普通文本以外的内容(例如,按下 CTRL 键),这个模块将帮助你解析那些信号。

  • 提示 : 15 请求用户输入可以简单到使用一个带有消息的 console.log,然后依赖 Deno 的 Stdin 阅读器,或者您可以使用这个包给用户一个很好的体验。除了请求自由文本输入,您还可以提供下拉框、复选框、数字输入等等。

  • 表格 : 16 如果您需要在终端上显示表格数据,这个模块就是您的首选。它允许您设置格式选项,如填充、边框宽度、最大单元格宽度等。

作为这个库可以做什么的一个例子,我将向您展示如何使用我刚才提到的最后一个模块在一个格式良好的表格上显示 CSV 文件的内容。

文件内容见图 5-4 。你会发现它没有什么特别之处,只是你的普通电子表格,我会把它保存为普通的 CSV 文件,并使用清单 5-12 中的代码,我会加载并显示它。在图 5-5 中,你会看到最终结果显示在我的终端上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-4

基本 CSV 文件

import { parse } from "https://deno.land/std/encoding/csv.ts";
import { BufReader } from "https://deno.land/std/io/bufio.ts";
import { Table } from 'https://deno.land/x/cliffy/table.ts';

const f = await Deno.open("./data.csv");
const reader = new BufReader(f)

const records:[string[]] = <[string[]]>(await parse(reader))

f.close();

Table.from( records )
.maxCellWidth( 20 )
.padding( 1 )
.indent( 2 )
.border( true )
.render();

Listing 5-12Deno code to display the content of our CSV in table format on the terminal

注意如何解析 CSV。我实际上使用的是 Deno 的标准库,table 模块期望得到与parse方法返回的格式相同的格式,所以我们在这里实际上不必做太多。输出本身正如我们所期望的那样,是我们终端上的一个表格。

img/501657_1_En_5_Fig5_HTML.jpg

图 5-5

显示表中数据的脚本输出

现在已经有很多其他的模块可以让你开始用 Deno 编写高质量的软件了。社区不断地发布和移植来自 Node 或 Go 的包,或者只是抓住机会给这个新的生态系统带来新鲜的想法,所以开始浏览和测试那些看起来更有趣的包真的取决于你。

结论

本章的目的是让您了解 Deno 的生态系统已经有多成熟,正如您所看到的,社区不仅对缺乏提供浏览和可靠存储代码的方式的包管理器做出了回应,而且他们还一直在制作内容,就像没有明天一样。

如果您想知道这个新的运行时是否有足够的用户群来实际用于生产,考虑到在发布后的几个月内已经发布的所有内容,本章应该会给你答案。

事情才刚刚开始,所以在下一章,也是最后一章,我将展示几个例子,说明如何使用本章中的一些模块和一些新的模块来创建成熟的应用。

www.arweave.org/

2

https://nest.land/package/deno-drash

3

https://drash.land

4

https://expressjs.com/

5

http://restify.com/

6

https://rahmanfadhil.github.io/cotton/

7

https://sequelize.org/

8

https://eveningkid.github.io/denodb-docs/

9

https://deno.land/x/mongo

10

https://github.com/c4spar/deno-cliffy/

11

https://github.com/c4spar/deno-cliffy/tree/master/packages/ansi-escape

12

https://github.com/c4spar/deno-cliffy/tree/master/packages/command

13

https://github.com/c4spar/deno-cliffy/tree/master/packages/flags

14

https://github.com/c4spar/deno-cliffy/tree/master/packages/keycode

15

https://github.com/c4spar/deno-cliffy/tree/master/packages/prompt

16

https://github.com/c4spar/deno-cliffy/tree/master/packages/table

六、将所有这些放在一起——示例应用

这是最后一章,到目前为止,我们不仅讨论了语言和运行时,还讨论了自发布之日起(老实说,在此之前)社区所做的令人惊叹的工作,构建工具和模块来帮助推动技术向前发展。

在这一章中,我将展示几个我用 Deno 构建的非常不同的项目,以便向您展示到目前为止所涉及的所有内容是如何组合在一起的。它们都是示例项目,当然还没有完全投入生产,但是它们应该涵盖所有感兴趣的领域,如果您将 GitHub 项目作为一个起点(所有这些项目都可以在 GitHub 帐户上使用),您应该能够对其进行定制,并很快使其成为您自己的项目。

所以事不宜迟,让我们开始检查项目。

Deno runner

我们要解决的第一个项目是一个简单但非常有用的项目。从我们到目前为止所介绍的内容来看,每次执行 Deno 脚本时,都需要指定权限标志,以便为脚本提供这些权限。这是事实,也是这个运行时背后的团队的设计决策。

然而,可以有另一种方式;如果您创建一个工具,从预设文件中读取这些权限,然后作为子进程执行预期的脚本,那么您可以为用户提供更好的体验。这就是这个项目的目的:简化执行 Deno 脚本的用户体验,而不必担心非常长的命令行,虽然很明确,但对于新手用户来说也可能很复杂和可怕。

目标是从这样的命令行移动:

$ deno run --allow-net --allow-read=/etc --allow-write=/output-folder --allow-env your-script.ts

取而代之的是,有一个专门设计的文件来存放你的安全标志,类似于清单 6-1 的东西,跑步者可以为你所用,而不必担心它。

--allow-net
--allow-read=/etc
--allow-write=/output-folder
--allow-env

Listing 6-1Content of the flags file

现在,一个更简单的命令行读取该文件,然后执行该脚本,如下所示:

$ the-runner your-script.ts

非常非常简单,如果您考虑一下,如果您尝试执行的脚本附带了 flags 文件,您会发现使用这个工具会更加友好,尤其是对新手而言。

计划

该工具很简单,并且使其工作所需的步骤也很简单:

  1. 构建一个入口点,它接收要作为参数执行的脚本的名称。

  2. 确保您可以找到标志文件(包含脚本安全标志的文件)。

  3. 使用标志文件中的标志和脚本的名称,创建执行脚本所需的命令。

  4. 然后,使用 Deno 的run方法执行它。

为了使这个工作,我们将只使用标准库;在某种程度上,这也证明了 Deno 的创造者对其标准库的承诺。

这个项目的结构也很简单;为了让一切井然有序,我们只需要几个文件:

  • 主脚本,即所谓的入口点,是将由用户执行的脚本,也是解析 CLI 参数的脚本。

  • 所有外部依赖项都将从deps.ts文件中导入,遵循已经覆盖的模式,以便于我们将来可能需要的任何更新或包含。

  • 我们将要编写的三个函数将存在于一个utils.ts文件中,只是为了将入口点的代码与这些支持函数分开。

  • 最后,将代码捆绑到单个文件并使其最终可执行所需的脚本将是一个简单的 bash 脚本。这是因为我们需要运行一些终端命令,使用 bash 比使用 JS 要容易得多。

代码

这个小项目的完整源代码位于这里 1 ,以防你需要检查任何其他细节或者甚至克隆存储库。

也就是说,入口点的代码公开了整个脚本背后的主要逻辑,您可以在清单 6-2 中看到这一点。

import { parse, bold } from './deps.ts'
import { parseValidFlags, runScript } from './utils.ts'

// The only argument we care about: the script's name
const ARGS = parse(Deno.args)
const scriptName:string = <string>ARGS["_"][0]

const FLAGFILE = "./.flags" //this is the location and the name of the flags file

// Required to turn the binary array from Deno.readFile into a simple string
const decoder = new TextDecoder('UTF-8')
let secFlags = ""
try { //Make sure we capture any error reading the file...
  const flags = await Deno.readFile(FLAGFILE)
  secFlags = decoder.decode(flags)
} catch (e) {//... and in that case, just ignore privileges
  console.log(bold("No flags file detected, running script without privileges"))
}

let validFlags:string[] = parseValidFlags(secFlags)
runScript(validFlags, scriptName)

Listing 6-2Code for the entry point script

脚本正在捕获位于Deno.args的命令行参数,由于parse方法(你将在deps.ts文件中看到)来自属于标准库的flags模块。然后,我们读取标志文件,如果脚本找不到它,就捕获它。有了这些内容,我们解析它,把它变成一个字符串列表,然后简单地请求运行它。

现在,关于代码的其余部分,我还想介绍两个细节。对标志的解析本质上需要读取一个带有标志列表的文件,每行一个标志,这有一个潜在的问题:如何将这些行转换成一个数组?请记住,换行字符并不总是相同的;这实际上取决于操作系统。幸运的是,Deno 为我们提供了一种方法来检测我们正在使用的行尾字符,因此脚本可以适应它运行的操作系统。您可以在清单 6-3 中看到我是如何做到的。

export function parseValidFlags(flags:string):string[] {
  const fileEOL:EOL|string = <string>detect(flags)
  if(flags.trim().length == 0) return []

  return <string[]>flags.split(fileEOL).map( flag => {
    flag = flag.trim()
    let flagData = findFlag(flag)
    if(flagData) {
      return flagData
    } else {
      console.log(":: Invalid Flag (ignored): ", bold(flag))
    }
  }).filter( f => typeof f != "undefined")
}

Listing 6-3Parsing the flags

注意所使用的detect函数,以便理解使用的是哪一个行尾字符。然后我们对split方法也这样做。剩下的就是确保从文件中读取的标志是有效的,如果不是,我们就忽略它。

最后,转换这些读取标志并运行脚本所需的代码如清单 6-4 所示。你可以看到这段代码有多简单;我们只需要用正确的参数调用Deno.run方法。

export function runScript(flags:string[], scriptFile:string) {
   flags.forEach( f => {
     console.log("Using flag", bold(f))
   })
   let cmd = ["deno", "run", ...flags, scriptFile]
   const sp = Deno.run({
     cmd
   })
   sp.status()
}

Listing 6-4Running the script

在这个函数中,我们对标志列表进行了额外的迭代,只是为了通知用户哪些权限被授予了正在执行的脚本。但是这段代码真正的核心是我们如何使用数组析构将数组合并到另一个数组中。

我想介绍的最后一点并不是真正的 Deno 代码。相反,它是几行 bash 代码。请参见清单 6-5 ,我稍后会解释。

#!/bin/bash

DENO="$(which deno)"
SHEBANG="#!${DENO} run -A"
CODE="$(deno bundle index.ts)"

BOLD=$(tput bold)
NORMAL=$(tput sgr0)

echo "${SHEBANG}
${CODE}" > bundle/denorun.js

chmod +x bundle/denorun.js

echo "----------------------------------------------------------------------------------"
echo "Thanks for installing DenoRunner, copy the file in ${BOLD}bundle/denorun.js${NORMAL} to a folder
you have in your PATH or add the following path to your PATH variable:

${BOLD}$(pwd)/bundle/${NORMAL}"
echo "----------------------------------------------------------------------------------"

Listing 6-5Build script written in bash

这个脚本的第一行被称为 shebang ,如果您从未见过它,它会告诉解释器将执行这个脚本的实际二进制文件的位置。它允许您执行脚本,而不必从命令行显式调用解释器;相反,当前的 bash 将为您做这件事。理解这一点很重要,因为它可以用任何脚本语言来完成,不仅仅是 bash,正如你马上要看到的,我们正试图对我们的脚本做同样的事情。

然后,我们捕获 deno 二进制文件在系统中的安装位置,以便创建一个包含新 shebang 行的字符串。根据您的系统,它可能看起来像这样:

/home/your-username/.deno/bin/deno run -A

然后我们将继续使用deno bundle命令,它将获取我们所有的外部和内部依赖项并创建一个文件。这对于分发我们的应用来说是完美的,因为它允许您简化这个任务。现在你不必要求你的用户下载一个潜在的非常大的项目,你只需要要求他们下载一个文件并使用它。

但是,我们的问题是,我们需要让我们的最终包是一个自动可执行文件,所以我们需要了解您的 deno 安装在哪里,以便创建正确的 shebang 行。将我们的包代码放在我们的CODE变量中,将 shebang 行放在SHEBANG变量中,然后我们将两个字符串输出到bundle文件夹中的一个文件(我们的最终包)中。然后,我们为我们的文件提供执行权限,这样您就可以从命令行直接调用它,shebang 就会生效。

将这一行作为脚本的第一行,您的 bash 将知道调用 Deno,告诉它执行我们新构建的文件,并为它提供所有可用的特权。这是为了确保我们不会遇到任何问题;您可以像过去一样更改-A以获得更详细的权限列表,但是一旦准备好,并且您已经将文件复制到您的PATH中的某个地方(即,当键入命令时您的终端将查找的某个地方)或者将文件夹添加到其中(参见清单 6-6 中如何做的示例),您就可以简单地键入

$ denorun.js your-script.ts

它会正确执行您的脚本,如果您创建了正确的.flags文件,它会读取并列出所有权限,在执行您的文件之前,它会列出这些权限以确保用户知道它们。

# To test it inside your current terminal window (will only work for the currently opened session)
export PATH="/path/to/deno-runner/bundle:$PATH"

# In order to make it work on every terminal
export PATH="/path/to/deno-runner/bundle:$PATH" >> ~/.bash_profile

Listing 6-6Adding a folder to your PATH variable

Note

清单 6-6 中的例子只适用于 Linux 和 Mac 系统;如果你有一个 Windows 盒子,你必须搜索如何更新你的路径。可以做到;这并不难,但是只需点击几下鼠标,而不是命令行。此外,该示例假设您正在使用默认的 bash 命令行;如果你正在使用别的东西,比如 Zsh, 2 ,你必须相应地更新代码片段。

测试应用

对于下一个使用 Deno 可以实现什么的例子,我想介绍标准库中另一个强大的模块:测试。 3

正如我已经提到的,Deno 已经为您提供了一个测试套件。当然,如果您打算做更复杂的事情,比如创建存根或模拟,您可能需要额外的资源,但是对于基本的设置,Deno 的测试模块已经足够了。

为此,我们将回到第一个示例,我们将添加一些示例测试,以便您可以看到它实际上有多简单。

添加一个测试就像创建一个以_test.ts或.test.ts结尾的文件一样简单(如果您直接编写 JavaScript,则更改扩展名);这样,当您使用如下的测试命令执行它时,Deno 应该能够获得它并运行测试:deno test。

清单 6-7 显示了设置测试套件所需的代码。

Deno.test("name of your test", () => {
  ///.... your test code here
})

Listing 6-7Basic test code

正如您所看到的,启动和运行您的测试只需要很少的东西;事实上,你可以在清单 6-8 中看到一个如何测试让 deno-runner 工作的一些函数的例子。

import { assertEquals } from "../deps.ts"
import { findFlag, parseValidFlags } from '../utils.ts'

Deno.test("findFlag #1: Find a valid flag by full name", () => {
  const fname = "--allow-net"
  const flag = findFlag(fname)
  assertEquals(flag, fname)
})

Deno.test("findFlag #2: It should not find a valid flag by partial name", () => {
  const fname = "allow-net"
  const flag = findFlag(fname)
  assertEquals(flag, false)
})

Deno.test("findFlag #3: Return false if flag can't be found", () => {
  const fname = "invalid"
  const flag = findFlag(fname)
  assertEquals(flag, false)
})

Deno.test("parseValidFlag #1: Should return an empty array if there are no matches", () => {
  let flags = parseValidFlags("")
  assertEquals(flags, [])
})

Listing 6-8Testing the deno-runner code

例如,如果您想做一些更复杂的事情并监视函数调用,您将需要一个外部模块,比如 mock。有了这个模块,你可以使用清单 6-9 中看到的间谍和模仿。

import { assertEquals } from "https://deno.land/std@0.50.0/testing/asserts.ts";
import { spy, Spy } from "https://raw.githubusercontent.com/udibo/mock/v0.3.0/spy.ts";

class Adder {
  public miniAdd(a: number, b:number): number {
   return a +b
  }
  public add( a: number, b: number, callback: (error: Error | void, value?: number) => void): void {
   const value: number = this.miniAdd(a,b)
   if (typeof value === "number" && !isNaN(value))    callback(undefined, value);
   else callback(new Error("invalid input"));
 }
}

Deno.test("calls fake callback", () => {
   const adder = new Adder()
   const callback: Spy<void> = spy();
   assertEquals(adder.add(2, 3, callback), undefined);
   assertEquals(adder.add(5, 4, callback), undefined);
   assertEquals(callback.calls, [
    { args: [undefined, 5] },
    { args: [undefined, 9] },
   ]);
});

Listing 6-9Using spies to test your code

该示例展示了如何覆盖回调函数并检查执行情况,从而允许您检查诸如执行次数、收到的参数等内容。事实上,清单 6-10 展示了如何为Adder类的一个方法创建存根以控制其行为的例子。

Deno.test("returns error if values can't be added", () => {
   const adder = new Adder()
   stub(adder, "miniAdd", () => NaN);
   const callback = (err: Error | void, value?: number) => {
      assertEquals((<Error>err).message, "invalid input");
   }
   adder.add(2, 3, callback)
});

Listing 6-10Creating a stub for one of the methods

只需一行简单的代码,您就可以用一个您可以控制的方法替换原来的方法。在清单 6-10 的例子中,您正在控制来自miniAdd方法的输出,从而帮助您测试与add方法相关联的其余逻辑(即,确保在这种情况下返回值是错误对象)。

聊天服务器

最后,构建聊天服务器通常需要处理套接字,因为它们允许您打开一个双向连接,该连接在关闭之前一直保持打开状态,这与普通的 HTTP 连接不同,普通的 HTTP 连接只存在很短的一段时间,并且实际上只允许在客户机和服务器之间发送单个请求及其相应的响应。

如果您来自 Node,您可能见过类似的基于套接字的聊天客户端和服务器的例子,本质上是在套接字库发出的事件之上工作。然而,Deno 的架构有点不同,因为它不依赖事件发射器,而是使用流来处理套接字。

在这个例子中,我将快速浏览 Deno 官方文档中显示的客户端和服务器的简化版本(对于 WebSocket 模块,是标准库 5 的一部分)。清单 6-11 展示了如何处理套接字流量(基本上,新消息被接收或者甚至是一个关闭套接字的请求)。

let sockets: WebSocket[] = []

async function handleWs(sock: WebSocket) {
 log.info("socket connected!");
 sockets.push(sock)
 try {
  for await (const ev of sock) {
    if (typeof ev === "string") {
      log.info("ws:Text", ev);
       for await(let s of sockets) {
        log.info("Sending the message: ", ev)
        await s.send(ev);
       }

      await sock.send(ev);
    } else if (isWebSocketCloseEvent(ev)) {
      // close
      const { code, reason } = ev;
      log.info("ws:Close", code, reason);
    }
  }
} catch (err) {
  log.error(`failed to receive frame: ${err}`);

  if (!sock.isClosed) {
    await sock.close(1000).catch(console.error);
  }
 }
}

Listing 6-11Handling new message on the socket connection

一旦建立了套接字连接,就要调用这个函数(稍后将详细介绍)。如您所见,它的要点是一个主for循环,遍历套接字的元素(实质上是新消息到达)。接收到的所有文本消息都将通过异步for循环中的socket.send方法发送回客户端和所有其他打开的套接字(注意代码中加粗的部分)。

为了启动服务器并开始监听新的套接字连接,您可以使用清单 6-12 中的代码。

const port = Deno.args[0] || "8080";
log.info(`websocket server is running on :${port}`);
for await (const req of serve(`:${port}`)) {
  const { conn, r: bufReader, w: bufWriter, headers } = req;
  acceptWebSocket({
    conn,
    bufReader,
    bufWriter,
    headers,
  })
   .then(handleWs)
   .catch(async (err:string) => {
      log.error(`failed to accept websocket: ${err}`);
      await req.respond({ status: 400 });
    });
  }

Listing 6-12Starting the server

使用serve函数启动服务器,这又创建了一个请求流,我们也在用异步for循环迭代这个请求流。在收到每个新的请求时(即打开一个新的套接字连接),我们调用acceptWebSocket函数。这个服务器和客户端的完整代码(我一会儿会讲到)可以在 GitHub、 6 上找到,所以一定要查看一下,以了解一切是如何组合在一起的。

简单的客户

没有合适的客户机,服务器什么也做不了,所以为了结束这个例子,我将向您展示如何使用标准库中的同一个模块来创建一个客户机应用,它将从前面连接到服务器并发送(和接收)消息。

清单 6-13 展示了客户端代码背后的基本架构;在使用了connectWebSocket函数之后,我们将创建两个不同的异步函数,一个用于从套接字读取消息,一个用于从标准输入读取文本。注意,除了标准库之外,我们没有使用任何外部库。

const sock = await connectWebSocket(endpoint);
console.log(green("ws connected! (type 'close' to quit)"));

// Read incoming messages
const messages = async (): Promise<void> => {
   for await (const msg of sock) {
      if (typeof msg === "string") {
         console.log(yellow(`< ${msg}`));
      } else if (isWebSocketCloseEvent(msg)) {
         console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`));
      }
   }
};

// Read from standard input and send over socket
const cli = async (): Promise<void> => {
   const tpr = new TextProtoReader(new  BufReader(Deno.stdin));
   while (true) {
      await Deno.stdout.write(encode("> "));
      const line = await tpr.readLine();
      if (line === null || line === "close") {
         break;
      } else {
      await sock.send(username + ":: " + line);
   }
 }
};
await Promise.race([messages(), cli()]).catch(console.error);

Listing 6-13Core of the client code

注意我之前提到的两个异步函数(messages和cli);它们都返回一个承诺,正因为如此,我们可以使用 Promise.race 让两个函数同时执行。使用这种方法,一旦任何一个承诺解决或失败,执行将结束。cli函数将从标准输入中读取输入,并使用socket.send方法通过套接字连接发送。

另一方面,messages函数就像在服务器端一样,迭代套接字的元素,本质上是对通过连接到达的消息做出反应。

通过将此客户端的实例连接到服务器,您可以在它们之间发送消息。服务器会负责将消息广播给每个人,客户端会用黄色显示从服务器收到的文本。如果你想测试这个项目,请参考完整代码 7 。

结论

这不仅是第六章的结尾,也是本书的结尾。希望到现在为止,您已经设法理解了创建 Deno 背后的动机,为什么提出 Node 并在后端开发行业留下印记的同一个人决定重新开始并更加努力。

Deno 远没有做到;事实上,当我开始编写这本书时,它的第一个版本刚刚发布,甚至不到两个月后,版本 1.2.0 就已经出来了,由于突破性的变化导致了一些问题。

但不要害怕;事实上,如果你对 Deno 背后的团队仍有疑虑,这就是你需要的证据。这不仅仅是一个人希望推翻后端的 JavaScript 国王,这是一个完整的团队,致力于满足不断增长的社区的需求,积极提供反馈和支持,以帮助生态系统每天都在增长。

如果你只是想从这本书里学到一样东西,我希望你带走玩一种全新技术的好奇心,希望你会爱上它。

感谢您阅读至此;下次再见!

https://github.com/deleteman/deno-runner

2

www.zsh.org/

3

https://deno.land/std/testing

4

https://deno.land/x/mock

5

https://deno.land/std/ws/

6

https://github.com/deleteman/deno-chat-example

7

https://github.com/deleteman/deno-chat-example

Deno 和 Fresh 入门 Deno 是一个 TypeScript 和 WebAssembly 运行时,它为 Node.js 的一些老问题提供了革命性的方法。Deno 的开发特别开始克服 Node 的一些限制,这些限制由其设计师 Ryan Dahl 确定,并在他 的 2018 年关于 Node.js 的 10 件事 中进行了描述。Ryan 开始使用 Rust(Node 是用 C++ 编写的)从头开始构建 Deno。Deno 使用 Google 的 V8 JavaScript 引擎,类似于 Node.js。 阅读详情

相关推荐

Deno初体验及实战入门

Deno初体验及实战入门 前言 最近学了一波Deno, 由于新东西 社区不完善,学的过程中都是翻英文文档和源码慢慢摸索,所以这里总结一些核心要点,帮助读者快速上手入门Deno,详细学习见官方手册 本文的代码例子见 https://github.com/HenryYey/deno-demo Deno是什么? deno是一个默认安全运行环境的JS/Ts/WebAssembly runtime,是Node.js之父 Ryan Dahl开发的新项目,号称是node的替代品,于2020年5月13日正式发布。他的名字由

HenryYey博客 1050

Deno 入门指南(一)

在过去的 10 年里,当后端开发人员听到“后端的 JavaScript”这个词时,所有人都会立即想到 Node.js。在这 10 年的开始,也许不会马上出现,但最终它的名字为每个人所知,成为另一种基于 JavaScript 的可用后端技术。凭借其现成的异步 I/O 功能(因为虽然其他技术也支持这一功能,但 Node 是第一个将它作为核心机制的技术),它为自己划分了一部分市场。

龙哥盟 1673

Deno:下载安装示例和打包为可执行文件

Deno:一个 安全的 JavaScript 和 TypeScript 运行时环境。

彭世瑜的博客 1687

Deno 快速入门

Deno 是一个JavaScript、TypeScript和WebAssembly运行时,具有安全的 默认值和出色的开发人员体验。它是基于V8引擎、 Rust和tokio。Deno是一款免费的开源软件,基于MIT许可证。

专注于大数据方向,区块链,前后端,数据可视化,人工智能等领域 2445

鸿蒙OpenHarmony南向开发 轻量系统芯片移植指南(一)

OpenHarmony系统采用"系统>子系统>部件"层级架构,支持功能模块化裁剪。本文介绍了关键子系统及移植方法:1)启动恢复子系统负责内核到应用间的进程初始化,需配置启动入口标识及链接脚本;2)文件子系统提供基础文件操作接口,需适配HAL层文件读写功能,可通过Flash模拟、轻量文件系统或厂商自有方案实现。移植过程需修改config.json配置,添加对应组件定义及功能实现。系统采用模块化设计,开发者可根据实际需求灵活配置所需子系统功能。

yx525623的博客 1131

Cursor概述及环境配置

Cursor 是一款基于 AI 的代码编辑器,支持 VS Code 配置迁移和 Java 开发环境配置。主要功能分为 Cursor Settings(AI 相关设置)和 Editor Settings(基础编辑器设置)。用户可通过一键导入或手动方式迁移 VS Code 配置,配置包括主题、扩展和快捷键等。对于 Java 开发,需配置 JDK 和 Maven 路径,并安装 Java 扩展插件以获得完整开发体验,如代码补全、调试和 Maven 项目管理。此外,Cursor 支持汉化配置,用户可安装中文语言包切换

Knight 3552

Deno插件开发入门:使用Rust扩展Deno功能的完整指南

Deno作为安全的JavaScript/TypeScript运行时,提供了强大的内置API,但有时我们需要通过插件扩展其功能。本指南将带你了解如何使用Rust语言开发Deno插件,从环境搭建到实际案例,帮助你快速掌握插件开发的核心技能。 ## 为什么选择Rust开发Deno插件? Rust语言以其内存安全、高性能和零成本抽象的特性,成为开发Deno插件的理想选择。通过Rust编写的插件,不仅可

gitblog_00757的博客 675

如何利用VS2017创建一个简单的窗口

#如何利用VS2017创建一个简单的窗口 1、新建->Windows桌面向导 2、应用程序类型->桌面应用程序,点击确定 3、点击调试->开始调试 可建立如下图的窗口 4、可以在生成的项目文件的中找到windows17_2的应用程序,打开界面如下: 注:新建空白项目也可以,注意在解决方案资源器中添加.cpp文件,如源.cpp文件,下载代码见博文 ...

weixin_46894139的博客 2914

Slack的Deno入门模板指南

Slack的Deno入门模板指南 欢迎来到Slack的Deno入门模板快速指南。本教程将引导您了解此开源项目的核心组件,包括目录结构、启动文件以及配置文件的细节,让您轻松上手基于Deno构建的Slack应用。 1. 目录结构及介绍 该项目遵循清晰的结构设计,以支持易于理解和维护的开发流程: index.ts - 应用程序的主要入口点,对于简单的示例,它通常包含了启动命令或服务逻辑。 tsc...

gitblog_00377的博客 714

Unity URP 深度解析:利用Stencil与RenderFeature实现高效遮挡高亮

本文深入解析Unity URP中利用Stencil与RenderFeature实现高效遮挡高亮的技术方案。通过模板缓冲机制和自定义RenderFeature,开发者可以在保持场景完整性的同时,清晰标识被遮挡物体位置,提升游戏体验。文章详细介绍了Shader编写、URP管线配置及性能优化技巧,并提供了常见问题排查方法。

weixin_29012677的博客 478

业态即战场:零售平台的生意模型与系统设计解构

在这篇文章中,我们从“控货、自营、联营”三种典型零售业态出发,拆解了亚马逊、阿里、京东和本地闪购平台在商品模型设计上的差异与博弈。看似简单的卖货方式背后,其实是平台在“控货权”“商品归属权”上的深层策略博弈:谁掌控商品,谁就掌控数据、流量与利润分配权。本文尝试用一套通俗但不失专业的方式,帮助产品经理和技术伙伴读懂零售平台商品模型的底层逻辑与系统设计演化路径。

曾经“等你生日那天”都遥远得像未来,如今却可欢愉的挥手说“下个十年见” 13万+

如何快速入门Deno开发?《Deno进阶开发笔记》带你从安装到实战

《Deno进阶开发笔记》是一份面向新手的Deno开发指南,通过简单易懂的步骤帮助开发者快速掌握Deno的安装配置与基础实战。Deno作为新一代JavaScript/TypeScript运行时,提供了更安全的执行环境和更简洁的开发体验,本笔记将带你轻松开启Deno开发之旅。 ## 🚀 准备工作:Deno安装指南 ### 选择合适的安装方式 Deno支持多种操作系统,推荐在**Mac OS**

gitblog_00437的博客 423

lammps构建高熵合金模型+结构优化初步筛选能量最小的结构

lammps构建高熵合金模型+结构优化初步筛选能量最小的结构

qq_45834835的博客 2604

Deno 钻研之术:从零开始的10个快速入门技巧终极指南 [特殊字符]

想要快速掌握Deno这个现代JavaScript运行时吗?《Deno 钻研之术》为你提供了完整的Deno学习路径!Deno是由Node.js创始人Ryan Dahl创建的安全TypeScript运行时,它内置了TypeScript支持、安全沙箱和现代化模块系统。无论你是JavaScript新手还是有经验的Node.js开发者,这10个快速入门技巧将帮助你轻松开启Deno编程之旅。 ## 📋 技

gitblog_00977的博客 874

把 sy-* 带进 ABAP CDS:ABAP 7.50 里的环境信息新姿势($session 与 @Environment.systemField 实战)

摘要:ABAP 7.50在CDS视图中引入两种获取环境信息的方式:1)直接使用$session会话变量读取用户、客户端和系统语言;2)通过@Environment.systemField注解参数,由Open SQL自动注入系统字段。$session方式简单但依赖Open SQL访问路径,非ABAP环境下可能失效;注解参数方案更工程化,依赖关系明确且支持测试。建议ABAP体系内优先使用$session,对外接口采用参数化方案。两种方式各有适用场景,正确选择可避免潜在风险。(148字)

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 152

使用R包PreMSIm预测微卫星不稳定的标题:基于基因表达量的微卫星不稳定性预测

在本文中,我们将介绍如何使用R语言中的PreMSIm包来根据基因表达量进行微卫星不稳定性的预测。需要注意的是,本文仅介绍了使用PreMSIm包进行微卫星不稳定性预测的基本流程和代码示例。在实际应用中,还需要考虑数据的质量控制、模型优化以及结果的解释和验证等因素,以确保预测结果的准确性和可靠性。预测结果将返回一个包含微卫星不稳定性指数的向量,其中每个元素对应一个样本的预测结果。在有了输入数据后,我们可以使用PreMSIm包中的函数进行微卫星不稳定性的预测。函数生成一个包含所有样本的微卫星不稳定性信息的表格。

2301_79330511的博客 382

使用Deno与Python共舞:deno_python深度指南

**deno_python** 是一个杰出的项目,它桥接了Deno runtime与Python解释器的世界,使得开发者能够在TypeScript或JavaScript项目中无缝地使用Python库。这一创新性的绑定不仅拓宽了Deno的应用范围,还允许开发人员利用Python强大的数据分析、机器学习等生态系统,而无需离开Deno环境。通过deno.land/x/python获取,该项目遵循MIT许

gitblog_01015的博客 885

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

2025远离Deno和Fresh

2023年底至2025年初这一年多时间里,Fresh没有实质开发进展。开发人员先是去做JSR,晾了Fresh几个月;回来后挖了个大坑(发起Fresh2),不久又去做Deno2,又晾了Fresh几个月;JSR和Deno2都完事后,依然没有回归开发Fresh2的任何迹象;几个月后才知道人家又被调去开发Deno Deploy新版啦,无语!

Liigo's blog 1280

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Deno极速入门

推荐阅读官方手册 起步 安装 鉴于国内的网速原因,@justjavac 大佬搞了国内的镜像加速: Mac/Linux curl -fsSL https://x.deno.js.cn/install.sh | sh Windows iwr https://x.deno.js.cn/install.ps1 -useb -outf install.ps1; .\install.ps1 # iwr https://x.deno.js.cn/install.ps1 -useb | iex 设置环境变量 den.

XiumingLee的博客 863

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

deno 初体验,实战记录一个node项目迁移到deno需要做什么

本文以csdnsynchexo迁移到deno实现进行一步步探索说明。 csdnsynchexo是一个爬取 csdn 博客内容生成 hexo 源文件内容的简单工具,正常版本使用 nodejs 实现,。最近 node 之父 ry 大神的 deno 也发布了 1.0,就想实践一下,从 node 版本迁移升级到 deno。本文主要记录一个 nodejs 应用迁移到 deno 需要做哪些工作,还涉及到一些非常基础的 deno 概念。如果你熟悉 nodejs,阅读本文的难度几乎为 0 迁移后项目github地址.

Geek技术前线 2571

Deno 开源项目入门指南

Deno 开源项目入门指南 【免费下载链接】deno denoland/deno: 是一个由 Rust 编写的新的 JavaScript 和 TypeScript 运行时,具有安全、快速和可扩展的特点。适合对 JavaScript、TypeScript 以及想要尝试新的运行时的开发者。 ...

gitblog_01150的博客 614

Powerlevel9k与Deno开发:deno_version segment配置指南

你是否在Deno开发时频繁切换项目,却无法快速识别当前环境版本?Powerlevel9k终端主题的自定义segment功能可帮你解决这一痛点。本文将详解如何创建`deno_version`状态段,让Deno版本信息实时显示在终端提示符中,提升开发效率。 ## 实现原理与环境准备 Powerlevel9k通过定义**自定义状态段(segment)** 实现个性化信息展示。每个segment由检测...

gitblog_01158的博客 1001

Deno 中文社区来了 deno.js.cn

Deno 中文社区来了,https://deno.js.cn ------------ 分割线 ----------- 10 年前的 2009 年 Node.js 首次发布,我从一名 Java 程序员转行为了 JavaScript 程序员。ry 也成为了我心中的偶像之一。 10 年后的 2019 年 Node.js 与 Deno 之父 ry 首次来中国旅游,期间给我发了一封邮件,邀请我在北京喝咖啡,并讨论一下 Deno 的未来开发计划。 去年我开始在国内写 Deno 技术文章,今年我成为了 Deno 核心

justjavac(迷渡) 2437

Deno TUI 项目安装与配置指南

Deno TUI 项目安装与配置指南 1. 项目基础介绍 Deno TUI 是一个使用 Deno 编写的模块,用于创建终端用户界面(Terminal User Interfaces,简称 TUI)。它提供了一系列易于使用的组件和反应性系统,允许开发者构建交互式的终端应用程序。本项目使用 TypeScript 语言开发,旨在提供一个无需依赖、轻量级且跨平台的终端界面解决方案。 2. 项目使用的关键技...

gitblog_01116的博客 964
上一篇: Deno 入门指南(一)
下一篇: Django CMS 入门指南(一)
绝不原创的飞龙
绝不原创的飞龙 优质创作者: 人工智能、数据科学与机器学习技术领域 优质创作者: 人工智能、数据科学与机器学习技术领域
博客等级 码龄15年 4万+粉丝 2万+原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值