Node.js 的事件驱动编程对于新手来说可能比较棘手,但这并不意味着难以入门。本文将介绍 Node.js 的基础知识,并解释其流行的原因。
要开始使用 Node.js,首先必须了解 Node.js 与传统服务器端脚本环境(如 PHP、Python 或 Ruby)的区别。
您很可能熟悉异步编程;毕竟,它是 AJAX 中的“A”。Node 中的每个函数都是异步的。因此,所有通常会阻塞线程的操作都使用 Promise 在后台执行。这是关于 Node 最重要的一点。例如,如果您正在读取文件系统上的文件,则将使用异步函数。
如果您使用的是某些版本的 Node 函数,则使用回调函数,这些函数是在 Promise 出现之前设计的。现在大多数 Node 函数都有 Promise 等效项,因此最好将此处使用的回调函数转换为基于 Promise 的等效项,并比较语法。
使用 Node,您必须自己完成很多工作。例如,HTTP 模块非常精简且不拘泥于特定风格。这对新手来说可能令人不知所措,但好处是能够构建高性能的 Web 应用(尽管 JavaScript 的性能很大程度上归功于 V8 优化的引擎)。一个脚本处理与所有客户端的所有通信。这大大减少了应用程序使用的资源数量。例如,这是一个简单的 Node.js 应用程序代码:
const i, a, b, c, max; max = 1000000000; var d = Date.now(); for (i = 0; i <p>以下是使用 PHP 编写的等效代码:</p> <pre class="brush:php;toolbar:false">$a = null; $b = null; $c = null; $i = null; $max = 1000000000; $start = microtime(true); for ($i = 0; $i <p>现在让我们看看基准测试数据。下表列出了这两个简单应用程序的响应时间(以毫秒为单位):</p> <pre class="brush:php;toolbar:false">const http = require('http');
http 变量。
在上面的代码中,我们将模块的名称传递给 exports 对象,并使用要公开的代码片段填充其属性和方法。考虑以下模块示例:
exports.area = function (r) { return Math.PI * r ** 2; }; exports.circumference = function (r) { return 2 * Math.PI * r; };
此代码创建了一个 exports 对象。这些函数可以在模块外部访问,因为它们是在 PI 上定义的,完全受到保护,免受外部干扰。因此,您可以放心,circumference() 将始终按预期工作(只要为 import 关键字提供值):
// file import myModule from "./myModule.js" // Node 内置/包 import http from "http"
在浏览器中,ESM 只能使用相对文件路径进行搜索,如上所示。但是,在 Node 中,您可以传递没有 node: 前缀的路径。
但是,以前的方法仅适用于默认导出。如果您使用的是命名导出(稍后将详细介绍),则需要使用稍微不同的语法。
import { exportOne, exportTwo } from "./myModule.js"
要导出内容,请使用 export default 关键字。export 用于命名导出,export default 用于默认导出。命名导出允许您导出不同的内容,并且仅使用其中一个在不同的模块中使用上面的 import 语法。如果您只导出一个内容,则默认导出会更容易。
// 命名导出 export function exportOne() { ... } export function exportTwo() { ... } // 默认导出 export default function defaultFunction() { ... }
在本教程的其余部分,我们将使用 ESM。
Node 是在 Google 的 V8 JavaScript 引擎中运行的 JavaScript 环境。因此,我们应该遵循我们在客户端开发中使用的最佳实践。例如,我们应该避免将任何内容放入全局作用域。但是,这并非总是可能的。Node 中的全局作用域是(在浏览器中为 window),您可以通过在声明变量时省略 var 来轻松创建函数的全局变量。
自然地,我们需要在编写和执行应用程序之前安装 Node。如果您使用的是 Windows 或 macOS,安装非常简单;nodejs.org 网站提供了这些操作系统的安装程序。对于 Linux,请使用任何包管理器。例如,如果您使用的是支持 apt 的发行版,请打开终端并键入:
sudo apt-get update sudo apt-get install node
或:
sudo aptitude update sudo aptitude install node
Node.js 位于 sid 存储库中;您可能需要将它们添加到您的源列表中:
sudo echo deb https://ftp.us.debian.org/debian/ sid main > /etc/apt/sources.list.d/sid.list
但请注意,在较旧的系统上安装 sid 包可能会破坏您的系统。请小心,并删除 module_name。
当然,我们的第一个 Node.js 脚本将打印在控制台中显示的文本“Hello World!”。
让我们继续一个更高级的应用程序;它并不像您想象的那么复杂。让我们从以下代码开始。阅读注释,然后阅读下面的解释:
// 包含 http 模块。 import { createServer } from "http" // 创建服务器。作为参数传递的函数在每次发出请求时都会被调用。 // request 变量保存所有请求参数 // response 变量允许您对发送到客户端的响应执行任何操作。 createServer(function (request, response) { // 在 end 事件上附加侦听器。 // 当客户端发送所有数据并等待响应时,将调用此事件。 request.on("end", function () { // 将标头写入响应。 // 200 是 HTTP 状态代码(此代码表示成功) // 第二个参数在对象中保存标头字段 // 我们正在发送纯文本,因此 Content-Type 应为 text/plain response.writeHead(200, { 'Content-Type': 'text/plain' }); // 发送数据并结束响应。 response.end('Hello HTTP!'); }); // 侦听 8080 端口。 }).listen(8080);
这段代码非常简单。您可以通过使用 response.end() 向客户端发送更多数据。将此代码保存为 http.js,然后在控制台中键入以下命令:
node http.js
打开浏览器并导航到 https://www.php.cn/link/7232a90ea7d391905f9ee07bcc7c5967。您应该在页面上看到文本 Hello HTTP!。
如前所述,我们必须自己完成 Node 中的所有工作,包括解析请求参数。但是,这相当简单。看看下面的代码:
// 包含 createServer import { createServer} from "http" // 和 url 模块,它在解析请求参数方面非常有用。 url = require("url"); // 创建服务器。 createServer(function (request, response) { // 在 end 事件上附加侦听器。 request.on('end', function () { // 解析请求参数并将它们存储在 _get 变量中。 // 此函数解析来自请求的 url 并返回对象表示。 var _get = url.parse(request.url, true).query; // 将标头写入响应。 response.writeHead(200, { 'Content-Type': 'text/plain' }); // 发送数据并结束响应。 response.end('Here is your data: ' _get['data']); }); // 侦听 8080 端口。 }).listen(8080);
此代码使用 query 属性,该属性检索 URL 的参数。将此文件保存为 get.js 并使用以下命令执行它:
node get.js
然后,导航到 data 参数不会中断脚本。
要管理 Node 中的文件,我们使用 fs 模块(核心模块)。我们分别使用 fs.writeFile() 方法读取和写入文件。我将在以下代码之后解释参数:
// 包含 createServer, import { createServer } from "http" // 和 fs 函数 import { readFile, writeFile } from "fs" // 创建 http 服务器。 createServer(function (request, response) { // 在 end 事件上附加侦听器。 request.on("end", function () { // 读取文件。 readFile("test.txt", 'utf-8', function (error, data) { // 写入标头。 response.writeHead(200, { 'Content-Type': 'text/plain' }); // 将从文件中获得的数字递增。 data = parseInt(data) 1; // 将递增的数字写入文件。 writeFile('test.txt', data); // 使用一些不错的消息结束响应。 response.end('This page was refreshed ' data ' times!'); }); }); // 侦听 8080 端口。 }).listen(8080);
将此保存为 files.js。在运行此脚本之前,在与 files.js 相同的目录中创建一个名为 test.txt 的文件。
此代码演示了 fs.writeFile() 方法。每次服务器收到请求时,脚本都会从文件中读取一个数字,递增该数字,并将新数字写入文件。fs.writeFile() 方法接受文件名和数据作为参数。它还接受第三个和第四个参数(两者都是可选的),分别指定编码和回调函数。
现在,让我们使用以下命令运行此脚本:
node files.js
在浏览器中以 https://www.php.cn/link/7232a90ea7d391905f9ee07bcc7c5967 打开它并刷新几次。现在,您可能会认为代码中存在错误,因为它似乎递增了两次。这不是错误。每次请求此 URL 时,都会向服务器发送两个请求。第一个请求是由浏览器自动发出的,它请求 favicon.ico,当然,第二个请求是针对 URL(https://www.php.cn/link/7232a90ea7d391905f9ee07bcc7c5967)。
即使此行为在技术上不是错误,但它也不是我们想要的行为。我们可以通过检查请求 URL 来轻松修复此问题。以下是修改后的代码:
// 包含 createServer, import { createServer } from "http" // 和 fs 函数 import { readFile, writeFile } from "fs" // 创建 http 服务器。 createServer(function (request, response) { // 在 end 事件上附加侦听器。 request.on('end', function () { // 检查用户是否请求 / if (request.url == '/') { // 读取文件。 readFile('test.txt', 'utf-8', function (error, data) { // 写入标头。 response.writeHead(200, { 'Content-Type': 'text/plain' }); // 将从文件中获得的数字递增。 data = parseInt(data) 1; // 将递增的数字写入文件。 writeFile('test.txt', data); // 使用一些不错的消息结束响应。 response.end('This page was refreshed ' data ' times!'); }); } else { // 指示未找到请求的文件。 response.writeHead(404); // 并在不发送任何数据的情况下结束请求。 response.end(); } }); // 侦听 8080 端口。 }).listen(8080);
现在测试它;它应该按预期工作。
大多数传统的服务器端技术都具有连接到数据库并查询数据库的内置方法。使用 Node.js,您必须安装一个库。在本教程中,我选择了稳定且易于使用的 node-mysql。此模块的全名是 mysql@2.0.0-alpha2(@ 之后的所有内容都是版本号)。打开控制台,导航到您已存储脚本的目录,然后执行以下命令:
npm install mysql
这将下载并安装模块,它还会在当前目录中创建 node_modules 文件夹。现在让我们看看如何在代码中使用它;请参见以下示例:
// 包含 http 模块, import { createServer } from "http" // 和您刚刚安装的 mysql 模块。 import * as mysql from "mysql" // 创建连接。 // 数据默认为新的 mysql 安装,应根据您的配置进行更改。 const connection = mysql.createConnection({ user: "root", password: "", database: "db_name" }); // 创建 http 服务器。 createServer(function (request, response) { // 在 end 事件上附加侦听器。 request.on('end', function () { // 查询数据库。 connection.query('SELECT * FROM your_table;', function (error, rows, fields) { response.writeHead(200, { 'Content-Type': 'x-application/json' }); // 将数据作为 JSON 字符串发送。 // Rows 变量保存查询的结果。 response.end(JSON.stringify(rows)); }); }); // 侦听 8080 端口。 }).listen(8080);
使用此库查询数据库很容易;只需输入查询字符串和回调函数即可。在实际应用程序中,您应该检查是否存在错误(如果发生错误则为 undefined)并根据查询的成功或失败发送响应代码。另请注意,我们已设置 x-application/json,这是 JSON 的有效 MIME 类型。使用 JSON.stringify()
方法将 rows 转换为 JSON 结构。
将此文件保存为 mysql.js,然后执行它(如果您已安装 MySQL):
node mysql.js
在浏览器中导航到 https://www.php.cn/link/7232a90ea7d391905f9ee07bcc7c5967,您应该会收到下载 JSON 格式文件的提示。
Node.js 需要额外的工作,但快速而强大的应用程序的回报是值得的。如果您不想在最低级别上完成所有工作,您可以随时选择一个框架(例如 Express)来简化应用程序的开发。
Node.js 是一项很有前景的技术,也是高负载应用程序的绝佳选择。微软、eBay 和雅虎等公司已经证明了这一点。如果您不确定托管您的网站或应用程序,您可以随时使用廉价的 VPS 解决方案或各种基于云的服务,例如 Microsoft Azure 和 Amazon EC2。这两种服务都以合理的价格提供可扩展的环境。
以上是node.js初学者的详细内容。更多信息请关注PHP中文网其他相关文章!