node.js基础知识学习笔记

一、node是什么?

官方解释

  • node.js is a JavaScript runtime built on chrome's V8 JavaScript engine

  • JavaScript-提供灵活的语法 ; V8-为JavaScript运行提供足够高的效率和实现

  • Node.js 是单进程单线程应用程序,但是因为V8引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高

  • 编译语言的运行环境(编译器+操作系统的底层支持)

  • node=c++代码编写+ECMAScript语法规范


个人理解

  • JavaScript可以在后端运行的一个环境

  • Node.js开发的目的就是为了用JavaScript编写Web服务器程序。

  • JavaScript实际上已经统治了浏览器端的脚本,其优势就是有世界上数量最多的前端开发人员。

  • 如果已经掌握了JavaScript前端开发,再学习一下如何将JavaScript应用在后端开发,就是名副其实的全栈了。


node 特点

在Node上运行的JavaScript相比其他后端开发语言有何优势

  • 最大的优势是借助JavaScript天生的事件驱动机制加V8高性能引擎,使编写高性能Web服务轻而易举。

  • 其次,JavaScript语言本身是完善的函数式语言,在前端开发时,开发人员往往写得比较随意,让人感觉JavaScript就是个“玩具语言”。但是,在Node环境下,通过模块化的JavaScript代码,加上函数式编程,并且无需考虑浏览器兼容性问题,直接使用最新的ECMAScript 6标准,可以完全满足工程上的需求。

Node 自带了交互式解释器REPL

同步操作异步操作

同步操作的好处是代码简单,缺点是程序将等待IO操作,在等待时间内,无法响应其它任何事件。而异步读取不用等待IO操作,但代码较麻烦。

1、组成

  • 引入 required 模块:我们可以使用 require 指令来载入 Node.js 模块。
  • 创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
  • 接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。

2、内部机制?

  • node中的IO:node程序在Libuv支持下与系统磁盘和网络交互的过程
  • node没有提供多线程的支持,用户编写的代码只能运行在当前线程中
  • 开发者无法在一个独立进程中添加新的线程,但是可以派生出多个进程来达到并行完成工作的目的
  • node中的并发:node虽然运行在单线程中,但任然支持高并发,就是依靠事件循环实现的

二、node模块化系统

为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统;Node.js 提供了 exports 和 require 两个对象

  • exports 是模块公开的接口
  • require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。

1、javascript模块规范

1.1、commonJS

  • commonJS将每个文件都看作一个模块,模块内部的定义的变量都是私有的,无法被其他模块使用
  • 模块加载是同步的,受限于宽带速度。
  • 代表:nodeJs

1.2、AMD

  • Asynchronous Module Definition 异步模块定义,他采用异步方式加载模块,模块的加载不影响他后面语句的进行。
  • 代表:RequireJs

2、基础模块fs

值得注意的路径问题

nodejs官方推荐在使用fs模块读取文件时使用绝对路径,而不是相对路径

let PUBLIC_PATH = path.resolve(__dirname, '../public')

fs模块同时提供同步和异步方法

读取文件

读取文本文件

sample.txt文件必须在当前目录下
且文件编码为utf-8


'use strict';

var fs = require('fs');

fs.readFile('sample.txt', 'utf-8', function (err, data) {
    if (err) {
        console.log(err);
    } else {
        console.log(data);
    }
});
复制代码

读取二进制文件

  • 当读取二进制文件时,不传入文件编码时,回调函数的data参数将返回一个Buffer对象。

  • 在Node.js中,Buffer对象就是一个包含零个或任意个字节的数组(注意和Array不同)。

  • Buffer对象可以和String作转换,例如,把一个Buffer对象转换成String:

'use strict';

var fs = require('fs');

fs.readFile('sample.png', function (err, data) {
    if (err) {
        console.log(err);
    } else {
        console.log(data);
        console.log(data.length + ' bytes');
    }
});
复制代码

同步读取文件

同步读取的函数和异步函数相比,多了一个Sync后缀,并且不接收回调函数,函数直接返回结果
如果同步读取文件发生错误,则需要用try...catch捕获该错误:

'use strict';

var fs = require('fs');

var data = fs.readFileSync('sample.txt', 'utf-8');
console.log(data);
复制代码
try {
    var data = fs.readFileSync('sample.txt', 'utf-8');
    console.log(data);
} catch (err) {
    // 出错了
}
复制代码

写文件

往文本文件中写入数据

'use strict';

var fs = require('fs');

var data = 'Hello, Node.js';
fs.writeFile('output.txt', data, function (err) {
    if (err) {
        console.log(err);
    } else {
        console.log('ok.');
    }
});
复制代码

同步写入

'use strict';

var fs = require('fs');

var data = 'Hello, Node.js';
fs.writeFileSync('output.txt', data);
复制代码

获取文件信息stat

'use strict';

var fs = require('fs');

fs.stat('sample.txt', function (err, stat) {
    if (err) {
        console.log(err);
    } else {
        // 是否是文件:
        console.log('isFile: ' + stat.isFile());
        // 是否是目录:
        console.log('isDirectory: ' + stat.isDirectory());
        if (stat.isFile()) {
            // 文件大小:
            console.log('size: ' + stat.size);
            // 创建时间, Date对象:
            console.log('birth time: ' + stat.birthtime);
            // 修改时间, Date对象:
            console.log('modified time: ' + stat.mtime);
        }
    }
});
复制代码

运行结果

isFile: true
isDirectory: false
size: 181
birth time: Fri Dec 11 2015 09:43:41 GMT+0800 (CST)
modified time: Fri Dec 11 2015 12:09:00 GMT+0800 (CST)
复制代码

3、基础模块stream

  • 流的特点是数据是有序的,而且必须依次读取,或者依次写入,不能像Array那样随机定位
  • 在Node.js中,流也是一个对象,我们只需要响应流的事件就可以了
  • data事件表示流的数据已经可以读取了
  • end事件表示这个流已经到末尾了,没有数据可以读取了
  • error事件表示出错了。

从文件读取数据时,可以打开一个文件流,然后从文件流中不断地读取数据

所有可以读取数据的流都继承自stream.Readable

data事件可能会有多次,每次传递的chunk是流的一部分数据

'use strict';

var fs = require('fs');

// 打开一个流:
var rs = fs.createReadStream('sample.txt', 'utf-8');

rs.on('data', function (chunk) {
    console.log('DATA:')
    console.log(chunk);
});

rs.on('end', function () {
    console.log('END');
});

rs.on('error', function (err) {
    console.log('ERROR: ' + err);
});
复制代码

向文件写入数据时,只需要把数据不断地往文件流中写进去就可以了

所有可以写入的流都继承自stream.Writable

'use strict';

var fs = require('fs');

var ws1 = fs.createWriteStream('output1.txt', 'utf-8');
ws1.write('使用Stream写入文本数据...\n');
ws1.write('END.');
ws1.end();

var ws2 = fs.createWriteStream('output2.txt');
ws2.write(new Buffer('使用Stream写入二进制数据...\n', 'utf-8'));
ws2.write(new Buffer('END.', 'utf-8'));
ws2.end();
复制代码

pipe

就像可以把两个水管串成一个更长的水管一样,两个流也可以串起来

一个Readable流和一个Writable流串起来后,所有的数据自动从Readable流进入Writable流,这种操作叫pipe

在Node.js中,Readable流有一个pipe()方法,k可以实现文件复制的类似操作

  • 默认情况下,当Readable流的数据读取完毕,end事件触发后,将自动关闭Writable流
  • 如果我们不希望自动关闭Writable流,需要传入参数: readable.pipe(writable, { end: false });
'use strict';

var fs = require('fs');

var rs = fs.createReadStream('sample.txt');
var ws = fs.createWriteStream('copied.txt');

rs.pipe(ws);
复制代码

4、基础模块http

  • 应用程序并不直接和HTTP协议打交道,而是操作http模块提供的request和response对象。
  • request对象封装了HTTP请求,我们调用request对象的属性和方法就可以拿到所有HTTP请求的信息;
  • response对象封装了HTTP响应,我们操作response对象的方法,就可以把HTTP响应返回给浏览器。
'use strict';

// 导入http模块:
var http = require('http');

// 创建http server,并传入回调函数:
var server = http.createServer(function (request, response) {
    // 回调函数接收request和response对象,
    // 获得HTTP请求的method和url:
    console.log(request.method + ': ' + request.url);
    // 将HTTP响应200写入response, 同时设置Content-Type: text/html:
    response.writeHead(200, {'Content-Type': 'text/html'});
    // 将HTTP响应的HTML内容写入response:
    response.end('<h1>Hello world!</h1>');
});

// 让服务器监听8080端口:
server.listen(8080);

console.log('Server is running at http://127.0.0.1:8080/');
复制代码

引入path模块和URL模块

URL模块

'use strict';

var url = require('url');

console.log(url.parse('http://user:pass@host.com:8080/path/to/file?query=string#hash'));
复制代码

输出结果

Url {
  protocol: 'http:',
  slashes: true,
  auth: 'user:pass',
  host: 'host.com:8080',
  port: '8080',
  hostname: 'host.com',
  hash: '#hash',
  search: '?query=string',
  query: 'query=string',
  pathname: '/path/to/file',
  path: '/path/to/file?query=string',
  href: 'http://user:pass@host.com:8080/path/to/file?query=string#hash' }
复制代码

path模块

'use strict';

var path = require('path');

// 解析当前目录:
var workDir = path.resolve('.'); // '/Users/michael'
 
// 组合完整的文件路径:当前目录+'pub'+'index.html':
var filePath = path.join(workDir, 'pub', 'index.html');
// '/Users/michael/pub/index.html'
复制代码

实现一个文件服务器

'use strict';

var
    fs = require('fs'),
    url = require('url'),
    path = require('path'),
    http = require('http');

// 从命令行参数获取root目录,默认是当前目录:
var root = path.resolve(process.argv[2] || '.');

console.log('Static root dir: ' + root);

// 创建服务器:
var server = http.createServer(function (request, response) {
    // 获得URL的path,类似 '/css/bootstrap.css':
    var pathname = url.parse(request.url).pathname;
    // 获得对应的本地文件路径,类似 '/srv/www/css/bootstrap.css':
    var filepath = path.join(root, pathname);
    // 获取文件状态:
    fs.stat(filepath, function (err, stats) {
        if (!err && stats.isFile()) {
            // 没有出错并且文件存在:
            console.log('200 ' + request.url);
            // 发送200响应:
            response.writeHead(200);
            // 将文件流导向response:
            fs.createReadStream(filepath).pipe(response);
        } else {
            // 出错了或者文件不存在:
            console.log('404 ' + request.url);
            // 发送404响应:
            response.writeHead(404);
            response.end('404 Not Found');
        }
    });
});

server.listen(8080);

console.log('Server is running at http://127.0.0.1:8080/');
复制代码

5、npm理解

定义:是什么

  • npm其实是Node.js的包管理工具(package manager)

意义: 为啥我们需要一个包管理工具呢?

因为我们在Node.js上开发时,会用到很多别人写的JavaScript代码。 如果我们要使用别人写的某个包,每次都根据名称搜索一下官方网站,下载代码,解压,再使用,非常繁琐。 于是一个集中管理的工具应运而生:大家都把自己开发的模块打包后放到npm官网上,如果要使用,直接通过npm安装就可以直接用,不用管代码存在哪,应该从哪下载。

使用严格模式

如果在JavaScript文件开头写上'usestrict';那么Node在执行该JavaScript时将使用严格模式。

但是,在服务器环境下,如果有很多JavaScript文件,每个文件都写上'usestrict'很麻烦。

我们可以给Nodejs传递一个参数,让Node直接为所有js文件开启严格模式: node --use_strict calc.js

怎样高效开发node程序

  • 使用文本编辑器来开发Node程序,最大的缺点是效率太低,运行Node程序还需要在命令行单独敲命令。如果还需要调试程序,就更加麻烦了。所以我们需要一个IDE集成开发环境,让我们能在一个环境里编码、运行、调试,这样就可以大大提升开发效率。

对比

  • Java的集成开发环境有Eclipse,Intellij idea等,
  • C#的集成开发环境有Visual Studio,
  • Node.js的集成开发环境:Visual Studio Code
  • 优点:启动速度快,执行简单,调试方便
  • 优点:可以跨平台Windows、Mac和Linux通用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值