DENO中的Webocket入门:教程和示例
#javascript #网络开发人员 #教程 #deno

如今

在某些编程语言或运行时环境中,Websocket是一个真正的挑战。人们经常利用社区创建的解决方案或使用服务来应对这一挑战,但是对于Deno来说,这非常简单。

介绍

在本文中,我们将创建一个带有两个端点的REST API,其中一个将负责发出事件,在这种情况下,该事件将与包含消息数据的文档相对应。另一个将建立将从服务器发送消息到客户端的Websocket连接的连接。

为您提供更多上下文,在本文中,我们将使用以下技术:

  • oak - web framework
  • evt-事件Emmiter替换

在开始本文之前,我建议您安装了Deno,并且使用节点有简短的经验。

设置项目

要开始,请导航到您选择的目录并运行以下命令:

deno init .

上面的命令有望在工作区中创建一组文件,因此,我们初始化了一个DENO项目,并将对deno.jsonc文件进行一些更改。

首先定义我们将使用任务Runner deno task
运行的一些命令

{
  "tasks": {
    "dev": "deno run --watch main.ts"
  }
}

接下来,让我们定义一些需要导入项目中的依赖项:

{
  // ...
  "imports": {
    "oak": "https://deno.land/x/oak@v12.5.0/mod.ts",
    "evt": "https://deno.land/x/evt@v2.4.22/mod.ts"
  }
}

随着deno.jsonc的最后一次更改,我们可以将项目的配置视为最终确定,现在该使我们的手变得脏了!

Websocket示例

EventEmitter的设置

下一步将是实例化将在API中使用的事件发射器,当我们使用依赖关系evt时,我们可以创建一个完全type typesafe客户端,而我们唯一需要的是定义类型并将其传递为通用在.create()方法中,这样:

// @/common/emitter.ts
import { Evt } from "evt";

export interface Todo {
  title: string;
  isDone: boolean;
  createdBy: string;
}

export const todoEmitter = Evt.create<Todo>();

路由器定义

考虑到上几点,我们现在可以定义本文简介中提到的每条路线。

首先,我们需要导入我们刚刚创建的事件发射器。然后,我们将使用HTTP动词POST创建路由,此路由旨在获取消息数据(在这种情况下为todo)。不忘记提及我们需要访问CreatedBy标头,因此以后我们将拥有必要的数据来发出事件。

// @/router.ts
import { Router } from "oak";

import { todoEmitter } from "./common/emitter.ts";

export const router = new Router();

router.post("/todos", async (ctx) => {
  const createdBy = ctx.request.headers.get("CreatedBy");
  if (!createdBy) ctx.throw(400);

  const { value } = ctx.request.body({ type: "json" });
  const data = await value;

  try {
    await todoEmitter.postAndWait({ ...data, createdBy });
    ctx.response.status = 200;
    ctx.response.body = { isSuccessful: true };
  } catch {
    ctx.throw(400);
  }
});

// ...

现在,我们已经在创建新的todo时发出了一个事件,我们现在可以创建GET路线。首先,我们必须检查连接是否可以升级,如果不是,我们返回错误。接下来,我们将访问CreatedBy标头以过滤发送给客户的消息。

实际上,todoEmitter也是异步迭代器,如果TODO的创建者与CreatedBy Header的创建者完全相同,我们可以直接迭代实例,然后发送Websocket。

// @/router.ts
import { Router } from "oak";

import { todoEmitter } from "./common/emitter.ts";

export const router = new Router();

// ...

router.get("/todos-ws", async (ctx) => {
  if (!ctx.isUpgradable) ctx.throw(501);

  const createdBy = ctx.request.headers.get("CreatedBy");
  if (!createdBy) ctx.throw(400);

  const ws = ctx.upgrade();

  for await (const todo of todoEmitter) {
    if (todo.createdBy === createdBy) {
      ws.send(JSON.stringify(todo));
    }
  }
});

现在我们可以说我们已经注册了每条路线,这使我们可以进入下一个和最后一步。

服务器定义

在此步骤中,我们将导入上一个点中创建的路由,并对API进行基本配置。这样:

// @/main.ts
import { Application } from "oak";

import { router } from "./router.ts";

const app = new Application({ logErrors: false });

app.use(router.routes());
app.use(router.allowedMethods());

app.listen({ port: 8000 });

要启动该过程,只需运行以下命令:

deno task dev

结论

我希望您能发现这篇文章有帮助,无论您是在现有项目中使用信息还是只是尝试一下。

如果您在文章中注意到任何错误,请告诉我。而且,如果您想查看本文的源代码,则可以在下面链接的github存储库上找到它。

Github Repo