给萌新的NodeJs技术栈教程(node篇4)--事件驱动和异步编程

72 阅读3分钟

在 Node.js 中,事件驱动和异步编程是核心概念。这些概念使 Node.js 能够高效地处理大量并发请求和 I/O 密集型任务。

事件驱动

事件驱动是一种编程范式,程序的执行流程由外部事件(如用户操作或系统事件)来驱动。在 Node.js 中,事件驱动主要通过 EventEmitter 类实现。EventEmitter 是 Node.js 的核心模块,它允许对象在发生特定事件时触发回调函数。

下面是一个简单的 EventEmitter 示例:

const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

const myEmitter = new MyEmitter();

myEmitter.on('hello', (name) => {
  console.log(`Hello, ${name}!`);
});

myEmitter.emit('hello', 'Alice');

在这个例子中,我们创建了一个名为 MyEmitter 的类,它继承自 EventEmitter。我们实例化了一个 myEmitter 对象,并使用 on() 方法监听名为 'hello' 的自定义事件。当我们使用 emit() 方法触发 'hello' 事件时,相应的回调函数会被调用。

事件循环

事件循环是 Node.js 异步编程的基础。它是一个持续运行的循环,用于处理并发请求、I/O 操作和计时器等任务。事件循环使 Node.js 能够在单线程中实现高并发处理。

事件循环的主要阶段包括:调度、I/O 回调、计时器回调等。事件循环会持续执行,直到所有任务都被处理完毕,或没有更多回调函数需要执行。

异步回调

异步回调是 Node.js 中处理异步操作的一种方式。当一个异步操作(如读取文件或查询数据库)完成时,回调函数将被添加到事件循环队列中,并在适当的时机被执行。

下面是一个异步回调的例子:

const fs = require('fs');

fs.readFile('example.txt', 'utf-8', (err, data) => {
  if (err) {
    console.error('Error reading file:', err);
  } else {
    console.log('File contents:', data);
  }
});

console.log('Reading file...');

Promise 和 async/await

Promise 是一种用于处理异步操作的对象。它代表一个尚未完成(或可能失败)的异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('Success');
  }, 1000);
});

myPromise
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.error(error);
  });

async/await 是基于 Promise 的一种更简洁的异步编程语法。使用 async/await,我们可以用看似同步的方式编写异步代码,提高代码的可读性和可维护性。使用 async/await,我们需要在包含异步操作的函数前加上 async 关键字,并在调用返回 Promise 的函数前加上 await 关键字。

下面是一个使用 async/await 的示例:

const fs = require('fs').promises;

async function readFileAsync() {
  try {
    const data = await fs.readFile('example.txt', 'utf-8');
    console.log('File contents:', data);
  } catch (err) {
    console.error('Error reading file:', err);
  }
}

readFileAsync();
console.log('Reading file...');

在这个例子中,我们使用了 fs.promises,它是 fs 模块的 Promise 版本。我们创建了一个名为 readFileAsyncasync 函数,并在其中使用 await 关键字等待 fs.readFile 的结果。这使我们的代码更简洁且易于阅读。

总结一下,事件驱动和异步编程是 Node.js 的核心概念,它们使 Node.js 能够高效处理大量并发请求和 I/O 密集型任务。事件循环是实现异步处理的关键,它在单线程中调度并执行回调函数。异步回调、Promise 和 async/await 是处理异步操作的主要方法,它们提供了不同程度的抽象和简化,使我们能够更轻松地编写和管理异步代码。希望能对大家有所帮助