Skip to content

2 - Node.js Basics

Install node

安装完成后,输入命令查看Node.js版本号:

node -v

Window object

JavaScript在浏览器中运行的时候,浏览器会提供全局的window对象,其中包含很多方法,例如定时器window.setTimeout, window.setInterval等等。

在Node环境里也有window对象,用法和在浏览器中一样。

DOM

Node环境中也不能(不需要)操作DOM,这是跟浏览器不一样的地方。

模块的导入/导出 Import/Export

Node.js中推荐使用 CommonJS 对模块导入导出。

自 Node.js v12 开始,你可以在 Node.js 中同时使用 require()import,而在浏览器中,你只能使用 import

CommonJS Module ✔

js
 // export:

const a = '哈哈哈哈';
const b = [1, 2, 3];

module.exports = { 
  aaa: a,
  bbb: b,
  // or
  // a, b
}
js
// require:

const {aaa, bbb} = require('./export');
console.log(aaa,  bbb);

ES Module

虽然Node从12版本就开始支持,但操作起来比较麻烦,参考https://nodejs.cn/api/esm.html#esm_ecmascript_modules

The File System 文件读写

想要读写文件,需要先引入fs模块:

js
const fs = require('fs');

read file

fs.readFile方法,接受两个参数:一个是文件地址,另一个是回调函数,回调函数中亦接受两个参数。

js
const fs = require('fs');

fs.readFile('./docs/blog1.txt', ((err, data) => {
  if (err) {
    console.log(err);
  }
  console.log(data.toString());
}));
console.log('done');

// 打印结果:
// done
// Buffer< xx, yy, ..>

writing files

fs.writeFile方法会覆盖原来的内容。同样的,第一个参数是文件的相对地址,第二个参数是内容,第三个参数是回调函数。

js
fs.writeFile('./docs/blog1.txt', 'hello world', () => {
  console.log('writing done.');
});

directories

可以先用fs.existsSync方法判断是否存在这个目录。如果在相同目录已存在时调用fs.mkdir,会报错。

js
// 是否存在
if (fs.existsSync('./assets')) {
	// 如果存在则remove
  fs.rmdir('./assets', (err) => {
    if (err) {
      console.log(err);
    }
    console.log('dir delete');
  })
} else {
	// 不存在则make
  fs.mkdir('./assets', (err) =>{
    if (err) {
      console.log(err);
    }
    console.log('done.');
  })
}

deleting files

直接贴代码,用的是fs.unlink

js
if (fs.existsSync('./docs/deleteme.txt')) {
  fs.unlink('./docs/deleteme.txt', (err) => {
    if (err) {
      console.log(err);
    }
    console.log('delete done.');
  })
}

流 Streams

Streams(流)是Node.js中的一个核心概念,它是一种处理流式数据的机制。在Node.js中,流可以将数据分成一系列小块,这些小块可以逐个地处理,从而提高数据处理的效率和性能。

在Node.js中,有四种类型的流:可读流(Readable)、可写流(Writable)、双工流(Duplex)和转换流(Transform)。其中,可读流用于读取数据,可写流用于写入数据,双工流既可以读取数据也可以写入数据,转换流用于在读取和写入数据之间进行转换。

想象你在加载一部电影时,不可能等电影所有的data都缓冲完毕才开始看这部电影,一般等一部分缓冲(Buffer)好就可以开始看了,这一小块一小块的data称之为chunk

一个资源,先是以stream的方式传到客户端,利用readStream.on()监听stream data,每当data装满一部分,就会被运送到客户端。

读取 readStream

假设我们有一个文件 ./docs/blog2.txt,即将通过stream传到客户端:

js
const fs = require('fs');

//这里创建了一个可读文件
const readStream = fs.createReadStream('./docs/blog2.txt');

// 监听事件
readStream.on('data', (chunk) => {
  // 一旦chunk存在,就打印内容
  console.log('-----new chunk-----');
  console.log(chunk);
})

运行文件,我们发现,控制台打印了分割线'-----new chunk-----'以及一大堆二进制的数据 <Buffer 61 61 61 61 ...>

写入 writeStream

除了readStream,我们还可以writeStream:

js
const fs = require('fs');

const readStream = fs.createReadStream('./docs/blog2.txt' );
// 在 blog3.txt 中写入内容
const writeStream = fs.createWriteStream('./docs/blog3.txt')

readStream.on('data', (chunk) => {
  console.log('-----new chunk-----');
  console.log(chunk);
  writeStream.write('hello \n');
  writeStream.write(chunk);
})

pipe

除了上面那种写法,还可以用pipe达到相同的目的。

在Node.js中,pipe(管道)是一种将可读流和可写流连接在一起的机制。通过使用pipe()方法,我们可以将一个可读流的输出直接连接到一个可写流的输入,从而实现数据的流式传输和处理。

js
const fs = require('fs');

const readStream = fs.createReadStream('./docs/blog2.txt' );
const writeStream = fs.createWriteStream('./docs/blog3.txt')

// 不需要监听读取文件了
// readStream.on('data', (chunk) => {
//   console.log('-----new chunk-----');
//   console.log(chunk);
//   writeStream.write('hello \n');
//   writeStream.write(chunk);
// })

// 读取文件后直接写入
readStream.pipe(writeStream);

Released under the MIT License.