• Deno入门:Node.js的现代替代品


    Deno 作为 Node.js 的现代替代品,提供了许多改进和创新,尤其是在安全性、模块系统和开发体验方面。虽然它仍处于发展阶段,但对于寻求简洁、安全和现代化 JavaScript/TypeScript 开发环境的开发者来说,Deno 是一个值得考虑的选择。随着社区的持续发展,Deno 的潜力和影响力有望进一步扩大。

    Deno基础知识

    • 内置的安全模型:Deno有严格的权限控制,如读写文件、网络访问等都需要明确的权限许可。
    • TypeScript支持:Deno默认支持TypeScript,可以提供更好的类型检查和开发体验。
    • ES模块:Deno使用URL或导入映射来导入模块,不同于Node.js的CommonJS模块系统。
    命令行工具:

    deno run:执行单个文件。
    deno test:运行测试。
    deno fmt:代码格式化。
    deno lint:代码风格检查。

    配置文件

    Deno的配置文件主要以deno.json为主,它可以包含多个配置选项来定制运行时的行为。而环境变量主要影响Deno的全局配置,如日志级别、缓存目录等。

    Deno配置文件 (deno.json)

    配置文件通常包含以下部分:

    1. permissions: 定义运行时的权限。
    2. importMap: 设置模块的导入映射。
    3. compilerOptions: TypeScript编译器的选项。
    4. lintRules: Lint规则(如果使用deno-lint)。
    5. watch: 监听文件变化并自动重新运行。
    6. reload: 自动重新加载模块。
    {
      "permissions": {
        "env": true,
        "net": ["*"],
        "read": ["./data"],
        "write": ["./output"]
      },
      "importMap": {
        "imports": {
          "lodash": "https://cdn.skypack.dev/lodash@4.17.21",
          "my-local-module": "./src/my-local-module.ts"
        }
      },
      "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "lib": ["dom", "deno.ns"],
        "strict": true
      },
      "lintRules": {
        // ...
      },
      "watch": true,
      "reload": {
        "enabled": true,
        "include": ["./src"]
      }
    }
    
    环境变量

    DENO_DIR: 指定Deno的配置、缓存和下载目录,默认为~/.deno。
    DENO_AUTH_TOKEN: 用于认证的令牌,用于访问私有模块。
    DENO_LOGGING_LEVEL: 控制日志级别,如debug, info, warn, error
    DENO_CACHE: 自定义缓存目录。
    DENO.land_proxy: 用于访问deno.land的代理设置。
    DENO_NO_COLOR: 如果设置,将禁用彩色输出。

    # Linux/MacOS
    export DENO_DIR=/path/to/custom/deno/dir
    export DENO_LOGGING_LEVEL=debug
    
    # Windows
    set DENO_DIR=%USERPROFILE%\custom\deno\dir
    set DENO_LOGGING_LEVEL=debug
    

    请注意,不是所有的配置选项都可以通过环境变量来设置,大部分配置仍然需要通过deno.json文件来定义。此外,Deno的权限通常是在运行命令时通过命令行标志指定,而不是通过配置文件或环境变量。例如,deno run --allow-read=./data your_script.ts

    创建HTTP服务器

    在Deno中创建一个HTTP服务器非常简单,可以使用内置的std/http库。

    // server.ts
    import { serve } from "https://deno.land/std/http/server.ts";
    
    const s = serve({ port: 8000 });
    console.log("Server is running on http://localhost:8000");
    
    for await (const req of s) {
      req.respond({ status: 200, body: "Hello, World!\n" });
    }
    
    1. 导入serve函数:import { serve } from “https://deno.land/std/http/server.ts”;从Deno的标准库中导入serve函数,这个函数用于创建HTTP服务器。

    2. 启动服务器:const s = serve({ port: 8000 });创建并启动服务器,监听8000端口。s是一个可迭代对象,代表服务器接收的每个请求。

    3. 打印服务器信息:console.log(“Server is running on http://localhost:8000”);告知用户服务器已经启动,并提供访问地址。

    4. 处理请求:for await (const req of s)是一个异步迭代器,它会等待并处理每一个到达的HTTP请求。req是ServerRequest类型的实例,包含了请求的信息。

    5. 响应请求:req.respond({ status: 200, body: “Hello, World!\n” });向客户端发送响应。status是HTTP状态码(这里是200,表示成功),body是响应体(这里是字符串"Hello, World!\n")。

    6. 运行服务器:在终端中,使用deno run --allow-net server.ts命令运行这个脚本。–allow-net标志是必需的,因为它允许Deno访问网络,这是创建服务器所必需的。

    获取远程数据

    在Deno中获取远程数据,通常使用fetch API

    // fetch_data.ts
    import { assert } from "https://deno.land/std/testing/asserts.ts";
    import { json as parseJson } from "https://deno.land/std/io/ioutil.ts";
    
    async function fetchData(url: string) {
      const response = await fetch(url);
      assert(response.ok, `Failed to fetch data: ${response.statusText}`);
    
      const data = await parseJson(await response.text());
      console.log(data);
    }
    
    // 示例URL,替换为你想要获取数据的URL
    const remoteDataURL = "https://jsonplaceholder.typicode.com/todos/1";
    fetchData(remoteDataURL);
    

    代码解析:

    导入模块:
    • assert用于断言,确保HTTP请求成功。
    • parseJson用于将接收到的文本转换为JSON对象。
    定义fetchData函数:
    • fetch(url)异步地发起HTTP GET请求到指定的URL。
    • response.ok检查HTTP状态码是否在200-299之间,表示请求成功。
    • response.text()获取响应体的文本内容。
    • parseJson(text)将文本内容解析为JSON对象。
    • console.log(data)打印解析后的数据。
    调用fetchData:
    • fetchData(remoteDataURL)使用示例URL调用函数,获取远程数据。
    运行脚本:
    • 在终端中,使用deno run --allow-net fetch_data.ts运行脚本。–allow-net是必需的,因为网络访问是默认禁止的。

    文件系统操作

    // file_operations.ts
    import { readTextFile, writeTextFile } from "https://deno.land/std/fs/mod.ts";
    
    // 读取文件
    const content = await readTextFile("example.txt");
    console.log(content);
    
    // 写入文件
    const newContent = "This is new content.";
    await writeTextFile("example.txt", newContent);
    

    网络编程

    // http_server.ts
    import { serve } from "https://deno.land/std/http/server.ts";
    
    const s = serve({ port: 8000 });
    
    console.log("Server is running on http://localhost:8000");
    
    for await (const req of s) {
      req.respond({ status: 200, body: "Hello, World!\n" });
    }
    

    异步编程

    Deno使用async/await语法进行异步操作,这使得代码更加简洁和易于理解。

    // async_example.ts
    import { delay } from "https://deno.land/std/async/mod.ts";
    
    async function asyncTask() {
      console.log("Task started...");
      await delay(1000); // 延迟1秒
      console.log("Task completed.");
    }
    
    asyncTask();
    
    异步文件操作
    // async_file.ts
    import { ensureDir, readTextFile, writeTextFile } from "https://deno.land/std/fs/mod.ts";
    import { delay } from "https://deno.land/std/async/mod.ts";
    
    async function asyncFileOps() {
      try {
        await ensureDir("output"); // 确保目录存在
        const content = await readTextFile("input.txt");
        console.log("Read content:", content);
    
        const newContent = "New content";
        await writeTextFile("output/output.txt", newContent);
        console.log("Wrote new content to output file.");
    
        await delay(2000); // 延迟2秒
        console.log("Finished async operations.");
      } catch (err) {
        console.error("An error occurred:", err);
      }
    }
    
    asyncFileOps();
    

    模块和标准库

    Deno的模块系统基于ES模块,允许你通过URL导入和导出代码。Deno的标准库提供了许多实用的模块,涵盖了文件系统操作、网络通信、HTTP服务器、JSON处理、加密和更多。

    导入标准库模块:
    // import_std.ts
    import { readTextFile } from "https://deno.land/std/fs/mod.ts";
    import { serve } from "https://deno.land/std/http/server.ts";
    
    // 使用readTextFile读取文件
    const content = await readTextFile("example.txt");
    console.log(content);
    
    // 创建HTTP服务器
    const s = serve({ port: 8000 });
    console.log("Server is running on http://localhost:8000");
    
    for await (const req of s) {
      req.respond({ status: 200, body: "Hello, World!\n" });
    }
    
    自定义模块:
    // my_module.ts
    export function add(a: number, b: number): number {
      return a + b;
    }
    
    // 在其他文件中导入
    // import_ts.ts
    import { add } from "./my_module.ts";
    
    console.log(add(2, 3)); // 输出 5
    

    标准库中的JSON处理:

    // json_example.ts
    import { readTextFile } from "https://deno.land/std/fs/mod.ts";
    import { json as parseJson } from "https://deno.land/std/json/mod.ts";
    
    const jsonData = await readTextFile("data.json");
    const data = parseJson(jsonData);
    console.log(data);
    
    标准库中的网络操作:
    // net_example.ts
    import { connect } from "https://deno.land/std/net/tcp.ts";
    
    const conn = await connect({ hostname: "localhost", port: 8000 });
    conn.write(new TextEncoder().encode("GET / HTTP/1.1\r\nHost: localhost:8000\r\n\r\n"));
    const response = new TextDecoder().decode(await Deno.readAll(conn));
    console.log(response);
    conn.close();
    
    使用deno.land/x第三方模块:
    // third_party_module.ts
    import { log } from "https://x.nest.land/log@0.1.0/mod.ts";
    
    log.info("This is an info message");
    

    Deno的标准库和第三方模块通常通过HTTPS URL导入,这提供了模块的版本控制和安全。deno.land是一个模块注册表,类似于npm,但专为Deno设计。x.nest.land是另一个Deno的模块仓库,提供了一些社区维护的模块。

    使用WebSocket

    在Deno中使用WebSocket,可以通过标准库或第三方库来实现。下面的示例将使用第三方库ws,这是一个流行的WebSocket库,适用于Deno和Node.js。

    首先,确保安装ws库:

    deno install -A -f --unstable --name deno_ws https://deno.land/x/ws@v1.1.0/mod.ts
    
    服务器端代码

    创建一个WebSocket服务器,监听客户端连接,并向连接的客户端发送消息。

    // server.ts
    import { Server } from "deno_ws/mod.ts";
    
    const server = new Server({ port: 8080 });
    
    server.on("connection", (socket) => {
      console.log("Client connected");
    
      socket.on("message", (message) => {
        console.log(`Received message => ${message}`);
        socket.send(`You sent -> ${message}`);
      });
    
      socket.on("close", () => {
        console.log("Client disconnected");
      });
    });
    
    console.log("WebSocket server is running on ws://localhost:8080");
    
    客户端代码

    创建一个WebSocket客户端,连接到上面的服务器,并发送/接收消息。

    // client.ts
    import { connect } from "deno_ws/mod.ts";
    
    const socket = connect("ws://localhost:8080");
    
    socket.on("open", () => {
      console.log("Connected to WebSocket server");
      socket.send("Hello, Server!");
    });
    
    socket.on("message", (message) => {
      console.log(`Received from server: ${message}`);
    });
    
    socket.on("close", () => {
      console.log("Connection closed");
    });
    
    运行示例

    打开两个终端窗口。

    在第一个窗口运行服务器:

    deno run --allow-net server.ts
    

    在第二个窗口运行客户端:

    deno run --allow-net client.ts
    
    服务器端:
    • 导入Server类并创建一个实例,监听8080端口。
    • 当有新的客户端连接时,触发connection事件,记录日志并设置消息处理器。
    • 对于每个接收到的消息,服务器会回送一条确认消息给客户端。
    • 当客户端断开连接时,触发close事件。
    客户端:
    • 使用connect函数连接到服务器指定的URL。
    • 设置open事件处理器,当连接建立时发送一条消息给服务器。
    • 设置message事件处理器,接收并打印来自服务器的消息。
    • 设置close事件处理器,记录连接关闭的事件。

    错误处理和调试

    错误处理

    Deno使用try/catch语句进行错误捕获,同时支持异步错误处理。示例:

    // error_handling.ts
    import { readFile } from "https://deno.land/std/fs/mod.ts";
    
    try {
      const data = await readFile("non_existent_file.txt");
    } catch (error) {
      if (error instanceof Deno.errors.NotFound) {
        console.error("File not found:", error);
      } else {
        throw error; // 未处理的错误继续抛出
      }
    }
    
    调试

    Deno的调试可以通过console.logconsole.error以及使用debugger语句配合IDE或浏览器的开发者工具进行。示例:

    // debug.ts
    function debugFunction(value) {
      debugger; // 这里会暂停执行,允许在调试器中检查上下文
      console.log("Debugging value:", value);
    }
    
    debugFunction("Debug me");
    

    性能优化

    1. 避免不必要的计算:只在需要时计算值,不要提前计算大量数据。
    2. 使用异步操作:对于I/O密集型任务,使用异步操作避免阻塞主线程。
    3. 缓存结果:对于重复计算的结果,可以考虑缓存。
    4. 使用类型检查:TypeScript的类型系统可以帮助避免运行时错误,提高代码质量。
    5. 限制权限:Deno的权限模型允许你精确控制代码的访问权限,避免不必要的资源消耗。

    以下是一个优化示例,使用deno.cache来缓存导入的模块:

    // optimized_import.ts
    import { cache } from "https://deno.land/x/deno.land_std@0.125.0/cache/mod.ts";
    
    const cachedModule = await cache(
      "https://deno.land/x/your_module@latest",
      ".cache",
    );
    
    // 现在可以从缓存中导入模块
    import * as mod from `${cachedModule}/mod.ts`;
    

    2500G计算机入门到高级架构师开发资料超级大礼包免费送!

  • 相关阅读:
    gitlab--基础--5.3--CICD--gitlab-ci.yml关键字
    Nginx反向代理服务器解决负责均衡问题
    系统架构设计:11 论湖仓一体架构及其应用
    使用LIO-SAM进行点云赋色 与 激光雷达和相机的精细化标定(防止自己忘记的博客)----- 激光雷达和相机的精细化标定
    C++ 核心指南之资源管理(下)智能指针最佳实践
    C++虚函数重载与虚表
    【云原生】Docker Compose安装使用详解
    微服务入门案例
    (黑马出品_05)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
    蜂蜡/聚苯乙烯大孔树脂微球/硫酸盐修饰聚苯乙烯微球/草莓状银/聚苯乙烯-丙烯腈复合微球的研究
  • 原文地址:https://blog.csdn.net/A1215383843/article/details/139425611