NodeJs基础

一、HelloWorld

1.1 安装nodemon工具

在编写调试Node.js项目,修改代码后,需要频繁的手动close掉,然后再重新启动,非常繁琐。现在,我们可以使用nodemon这个工具,它的作用是监听代码文件的变动,当代码改变之后,自动重启。

安装命令:

npm i nodemon -g

安装完成后,在任意目录下新建js文件,文件内容如下:

console.log('hello node.js');
console.log('hello java');
console.log('hello python');

执行命令:nodemon 文件路径,执行结果如下所示:
在这里插入图片描述
以后修改了js文件后,不需要每次重新运行node命令,提高开发效率。

二、模块使用

Nodejs内置一些模块,这些模块是nodejs本身提供,我们只需要在js文件中导入它们即可使用。下面简单介绍几个比较常用的模块:File System、OS、HTTP模块等。

资料地址:http://nodejs.cn/api/modules.html

2.1 文件模块

在 Node.js 模块系统中,每个文件都被视为一个独立的模块。如果要使用模块中导出的函数,那么就需要先导入模块。

下面使用fs模块读取文件的内容:

第一步:导入fs模块;

const fs = require('fs')

第二步:调用模块提供的函数;

// 以同步方式读文件
const data = fs.readFileSync('./config.js');
console.log('文件内容:', data);

// 以异步方式读文件
fs.readFile('./config.js', (data) => {
    console.log('文件内容:', data);
});

nodejs几乎所有的api都提供了同步和异步的版本。在实际开发中建议使用异步方式。但是有时我们需要对多个异步操作的执行顺序进行控制,这时我们可以把异步代码同步化。

让异步代码同步化的几种方式:

方式一:使用Promise;

const {promisify} = require('util')
// 将fs.readFile函数转换成Promise
const readFile = promisify(fs.readFile)
readFile('./config.js').then(data => console.log(data))

在nodejs的10.0以后版本,可以使用fs模块提供了promises对象,该对象也提供了readFile方法实现同步的读文件操作。

const {promises} = require('fs')
promises.readFile('./config.js').then(data => console.log(data.toString()))

方式二:使用generator函数;

function readFile(path) {
    return new Promise((resolve, reject) => {
        const data = fs.readFile(path, (err, data) => {
            if (err) {
                reject(err)
            } else {
                resolve(data);
            }
        });
    })
}

function* test() {
    yield readFile('./config.js');
    yield readFile('./config2.js');
}

const tt = test();
tt.next().value.then(res => {
    console.log('config.js文件内容:', res.toString());
})
tt.next().value.then(res => {
    console.log('config2.js文件内容:', res.toString());
})

方式三:使用async和await;

function readFile(path) {
    return new Promise((resolve, reject) => {
        const data = fs.readFile(path, (err, data) => {
            if (err) {
                reject(err)
            } else {
                resolve(data);
            }
        });
    })
}

async function test() {
    const p1 = await readFile('./config.js');
    console.log('config.js文件内容:', p1.toString())
    const p2 = await readFile('./config2.js');
    console.log('config2.js文件内容:', p1.toString())
}

test();

上面程序会先读去config.js文件内容,读完后再读取config2.js文件内容。

2.2 Buffer模块

Buffer代表缓冲器,用于在 TCP 流、文件系统操作、以及其他上下文中与八位字节流进行交互。

Buffer实例类似于从 0 到 255 之间的整数数组,它是一个8字节大小的数组,可存储二进制数据,但是以十六进制格式展示出来。Buffer 的大小在创建时确定,且无法更改。

Buffer 类在全局作用域中,因此无需使用 require(‘buffer’)。

创建Buffer的不同方式:

方式一:使用Buffer.alloc方法创建一个固定长度的Buffer;

const buf = Buffer.alloc(10)

方式二:把数组转换成Buffer;

const buf = Buffer.from([11, 22, 33])

方式三:把字符串转换成Buffer;

const buf = Buffer.from('hello world', 'utf-8')

Buffer提供了toString方法,用于读取Buffer中的数据。

buf.toString('utf-8')

合并多个Buffer:

const buf1 = Buffer.from('hello ')
const buf2 = Buffer.from('world ')
const buf3 = Buffer.concat([buf1, buf2])
console.log(buf3.toString());

2.3 http模块

Node.js 中的 HTTP 接口旨在支持传统上难以使用的协议的许多特性。 特别是,大块的、可能块编码的消息。 接口永远不会缓冲整个请求或响应,用户能够流式传输数据。

http头消息:

{ 
	'content-length': '123',
 	'content-type': 'text/plain',
  	'connection': 'keep-alive',
  	'host': 'mysite.com',
  	'accept': '*/*' 
}

为了支持所有可能的 HTTP 应用程序,Node.js 的 HTTP API 都非常底层。 它仅进行流处理和消息解析。 它将消息解析为消息头和消息主体,但不会解析具体的消息头或消息主体。

要使用 HTTP 服务器和客户端,必须 require(‘http’)。

下面我们使用http模块开发一个简单版的web服务器。

第一步:创建一个js文件,导入http模块以及其他相关模块;

const http = require('http')
const fs = require('fs')
const path = require('path')

第二步:调用http接口的createServer方法,该方法用于创建一个Http服务端;

const server = http.createServer((req, res) => {
    console.log('url: ', req.url); // 输出 /
    console.log('method: ', req.method); // 输出 get
    // 向客户端发送响应消息
    res.write('hello ');
    res.write('world ');
    res.write('nodejs ');
    res.end('java');
})

第三步:调用listen方法监听某个端口;

server.listen(3000)

res.end()方法用于结束请求,否则客户端会一直处于等待状态。

2.4 流

流(stream)是 Node.js 中处理流式数据的抽象接口。 stream 模块用于构建实现了流接口的对象。

Nodejs提供四种不同类型的流:

  • writable - 可写入数据的流(例如 fs.createWriteStream())。
  • Readable - 可读取数据的流(例如 fs.createReadStream())。
  • Duplex - 可读又可写的流(例如 net.Socket)。
  • Transform - 在读写过程中可以修改或转换数据的 Duplex 流(例如 zlib.createDeflate())

下面使用stream来完成文件的读写操作:

const fs = require('fs')

const inStream = fs.createReadStream('./config.js')
const outStream = fs.createWriteStream('./config2.js')

inStream.pipe(outStream)

在服务端向客户端输出图片:

if (req.headers.accept.indexOf('image/*') !== -1 && method === 'GET') {
	 fs.createReadStream(path.resolve('.' + url)).pipe(res)
}

上面程序代码中的响应对象res其实也是一个输出流。如果可以在pipe方法中直接把res作为参数传入。

三、express使用

Express 是一个保持最小规模的灵活的 Node.js Web 应用程序开发框架,为 Web 和移动应用程序提供一组强大的功能。

express主要解决nodejs开发中的两个主要问题:路由和请求流程控制。

3.1 如何使用express

第一步:安装express;

npm i express

第二步:新建一个js文件,导入express模块;

const express = require('express')

第三步:调用express函数,该函数返回一个对象;

const app = express()

第四步:调用对象方法处理请求;

第五步:调用对象的listen方法,指定要监听的端口;

下面演示express工具的简单用法:

const express = require('express')
const fs = require('fs')
const path = require('path')

// 创建express对象
const app = express()

app.get('/', (req, res) => {
    fs.readFile(path.resolve('./index.html'), (err, data) => {
        if (err) {
            res.statusCode = 500;
            res.end('server err!')
        } else {
            res.statusCode = 200 // 请求成功
            res.setHeader('content-type', 'text/html;charset=utf-8') 
            res.end(data)
        }
    })
})

app.listen(3000)

3.2 实现简单版的express

第一步:新建一个js文件,导入需要用到的模块;

const http = require('http')
const url = require('url')

第二步:定义一个数组变量,用于存储所有路由;

let routers = [] // 路由列表

第三步:创建一个主类,定义get方法;

get(path, handler) {
    // 保存路由
    routers.push({path, method: 'get', handler})
}

第四步:定义listen方法;

listen(port) {
    http.createServer((req, res) => {
        // url.parse方法可以把req.url的各个部分分解出来
        let {pathname} = url.parse(req.url, true)
        // 判断该pathname在路由列表中是否存在
        // 如果存在,在执行对应的handler函数
        routers.forEach(v => {
            if (v.path === pathname) {
                v.handler(req, res)
                return
            }
        })
    }).listen(port)
}

第五步:定义导出;

module.exports = function() {
    return new Application()
}
发布了109 篇原创文章 · 获赞 39 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章