一、node.js特征
- Node.js 异步编程的直接体现就是回调。
- Node.js 是单进程单线程应用程序,但是因为 V8 引擎提供的异步执行回调接口,通过这些接口可以处理大量的并发,所以性能非常高。
二、npm常用命令
- npm help 查看所有命令
- npm help 可查看某条命令的详细帮助,例如npm help install。
- 在package.json所在目录下使用npm install . -g可先在本地安装当前命令行程序,可用于发布前的本地测试。
- 使用npm update 可以把当前目录下node_modules子目录里边的对应模块更新至最新版本。
- 使用npm update -g可以把全局安装的对应命令行程序更新至最新版。
- 使用npm cache clear可以清空NPM本地缓存,用于对付使用相同版本号发布新版本代码的人。
- 使用npm unpublish @可以撤销发布自己发布过的某个版本代码。
三、命令
- 项目终端输入
node --version
查看版本,如果没版本号就是没安装
- npm -v 查看npm版本
四、使用npm命令安装模块
- npm install express ; npm install express -g 全局安装
npm 命令安装常用的 Node.js web框架模块 express:
安装好之后,express 包就放在了工程目录下的 node_modules 目录中,因此在代码中只需要通过 require(‘express’) 的方式就好,无需指定第三方包路径。
使用:var express = require('express');
- 使用npm卸载模块
npm uninstall express
- 使用npm更新模块
npm update express
- 使用npm搜索模块
npm search express
- 终端输入 node xxx.js 启动该文件
八、package.json
package.json 位于模块的目录下,用于定义包的属性
// Package.json 属性说明
name - 包名。
version - 包的版本号。
description - 包的描述。
hompage - 包的官网 url 。
author - 包的作者姓名。
contributors - 包的其他贡献者姓名。
dependencies - 依赖包列表。如果依赖包没有安装,npm 会自动将依赖包安装在 node_module 目录下。
repository - 包代码存放的地方的类型,可以是 git 或 svn,git 可在 Github 上。
main - main 字段指定了程序的主入口文件,require('moduleName') 就会加载这个文件。这个字段的默认值是模块根目录下面的 index.js。
keywords - 关键字
九、创建模块
创建模块,package.json 文件是必不可少的。我们可以使用 NPM 生成 package.json 文件,生成的文件包含了基本的结果。
npm init
Press ^C at any time to quit.
name: (node_modules) runoob # 模块名
version: (1.0.0)
description: Node.js 测试模块(www.runoob.com) # 描述
entry point: (index.js)
test command: make test
git repository: https://github.com/runoob/runoob.git # Github 地址
keywords:
author:
license: (ISC)
About to write to ……/node_modules/package.json: # 生成地址
{
"name": "runoob",
"version": "1.0.0",
"description": "Node.js 测试模块(www.runoob.com)",
……
}
Is this ok? (yes) yes
以上的信息,你需要根据你自己的情况输入。在最后输入 “yes” 后会生成 package.json 文件。
接下来我们可以使用以下命令在 npm 资源库中注册用户(使用邮箱注册):
$ npm adduser
Username: mcmohd
Password:
Email: (this IS public) mcmohd@gmail.com
接下来我们就用以下命令来发布模块:
$ npm publish
通过以上步骤我们自己创建的模块就可以跟其他模块一样使用 npm 来安装。
十、使用淘宝npm镜像
由于国内直接使用 npm 的官方镜像是非常慢的,这里推荐使用淘宝 NPM 镜像。
淘宝 NPM 镜像是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。
你可以使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:
$ npm install -g cnpm --registry=https://registry.npmmirror.com
这样就可以使用 cnpm 命令来安装模块了:
$ cnpm install [name]
更多信息可以查阅:https://npmmirror.com/。
nodejs
- node.js应用由哪几部分组成
1.引入required模块:我们可以使用 require 指令来载入 Node.js 模块。
2.创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
3.接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。
十一、Node.js REPL(交互式解释器)
Node.js REPL(Read Eval Print Loop:交互式解释器) 表示一个电脑的环境,类似 Windows 系统的终端或
Unix/Linux shell,我们可以在终端中输入命令,并接收系统的响应Node 自带了交互式解释器,可以执行以下任务:
读取 - 读取用户输入,解析输入的 Javascript 数据结构并存储在内存中。
执行 - 执行输入的数据结构
打印 - 输出结果
循环 - 循环操作以上步骤直到用户两次按下 ctrl-c 按钮退出。
- 启动Node的终端
在项目终端输入 node来启动node终端,通过回车来计算结果
- 简单的表达式运算
PS D:\work\lx\nodejs> node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> 1 +4
5
> 5/2
2.5
> 3*6
18
> 1 + (2*3)-4
3
>
- 使用变量
你可以将数据存储在变量中,并在你需要的时候使用它。
变量声明需要使用 var 关键字,如果没有使用 var 关键字变量会直接打印出来。
使用 var 关键字的变量可以使用 console.log() 来输出变量。
PS D:\work\lx\nodejs> node
Welcome to Node.js v13.14.0.
Type ".help" for more information.
> x=10
10
> var y=10
undefined
> x+y
20
> console.log("hello")
hello
undefined
>
- 多行表达式
Node REPL 支持输入多行表达式,这就有点类似 JavaScript。接下来让我们来执行一个 do-while 循环:
> var x = 0
undefined
> do {
... x++;
... console.log("x:"+x);
... } while(x<5);
x:1
x:2
x:3
x:4
x:5
undefined
>
… 三个点的符号是系统自动生成的,你回车换行后即可。Node 会自动检测是否为连续的表达式。
- 下划线_变量
你可以使用下划线(_)获取上一个表达式的运算结果:
> var x = 10
undefined
> y = 30
30
> x+y
40
> var sum = _
undefined
> console.log(sum)
40
undefined
>
- REPL 命令
ctrl + c - 退出当前终端。
ctrl + c 按下两次 - 退出 Node REPL。
ctrl + d - 退出 Node REPL.
向上/向下 键 - 查看输入的历史命令
tab 键 - 列出当前命令
.help - 列出使用命令
.break - 退出多行表达式
.clear - 退出多行表达式
.save filename - 保存当前的 Node REPL 会话到指定文件
.load filename - 载入当前 Node REPL 会话的文件内容。
十二、 Node.js 回调函数
Node.js 异步编程的直接体现就是回调。
异步编程依托于回调来实现,但不能说使用了回调后程序就异步化了。
回调函数在完成任务后就会被调用,Node 使用了大量的回调函数,Node 所有 API 都支持回调函数。
例如,我们可以一边读取文件,一边执行其他命令,在文件读取完成后,我们将文件内容作为回调函数的参数返回。这样在执行代码时就没有阻塞或等待文件
I/O 操作。这就大大提高了 Node.js 的性能,可以处理大量的并发请求。回调函数一般作为函数的最后一个参数出现:
function foo1(name, age, callback) { }
function foo2(value, callback1, callback2) { }
- 阻塞案例
var fs = require("fs");
var data = fs.readFileSync('input.txt');//Sync同步;执行完当前操作才能进行下一个操作
console.log(data.toString());
console.log('程序执行结束!');
-----------------
//执行结果
PS D:\work\lx\nodejs> node main.js
hello world nodejs;
程序执行结束!
- 非阻塞案例
var fs = require('fs');
fs.readFile('input.txt',function(err,data){//异步: 此操作的执行结不结束不影响后面其他代码执行
if(err) return console.log(err);
console.log(data.toString());
});
console.log('程序执行结束!');
-----------------
//执行结果
PS D:\work\lx\nodejs> node main2.js
程序执行结束!
hello world nodejs;
以上两个实例我们了解了阻塞与非阻塞调用的不同。第一个实例在文件读取完后才执行程序。
第二个实例我们不需要等待文件读取完,这样就可以在读取文件时同时执行接下来的代码,大大提高了程序的性能。因此,阻塞是按顺序执行的,而非阻塞是不需要按顺序的,所以如果需要处理回调函数的参数,我们就需要写在回调函数内
十三、事件驱动 程序
Node.js 有多个内置的事件,我们可以通过引入 events 模块,并通过实例化 EventEmitter 类来绑定和监听事件
- event emitters 事件发射器
- event handlers 事件处理程序
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
以下程序绑定事件处理程序:
// 绑定事件及事件的处理程序
eventEmitter.on('eventName', eventHandler);
我们可以通过程序触发事件:
// 触发事件
eventEmitter.emit('eventName');
- 实例
// 引入 event模块
var events = require('events');
//创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
//创建事件处理程序
var connectHandler = function connected(){
console.log('连接成功');
//触发 data_received 事件
eventEmitter.emit('data_received');
}
//绑定 connection事件处理程序
eventEmitter.on('connection',connectHandler);
//使用匿名函数绑定data_received 事件
eventEmitter.on('data_received',function(){
console.log('数据接收成功')
})
//触发 connection 事件
eventEmitter.emit('connection');
console.log('程序执行完毕');
十四、Node.js Buffer(缓冲区)
JavaScript 语言自身只有字符串数据类型,没有二进制数据类型,但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。
十五、Node.js模块系统
为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。
模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。
- 创建模块
exports.world = function() {
console.log('Hello World');
}
- 引入模块
var hello = require('./hello');/// 为当前目录,node.js 默认后缀为 js
hello.world();
Node.js 提供了 exports 和 require 两个对象,其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。
node.js 默认后缀为 js
- 有时候我们想把一个对象封装到模块里
module.exports = function() {
// ...
}
例子
//hello.js
function Hello() {
var name;
this.setName = function(thyName) {
name = thyName;
};
this.sayHello = function() {
console.log('Hello ' + name);
};
};
module.exports = Hello;
//main.js
var Hello = require('./hello');
hello = new Hello();
hello.setName('BYVoid');
hello.sayHello();
exports 和 module.exports 的使用 如果要对外暴露属性或方法,就用 exports就行,要暴露对象(类似class,包含了很多属性和方法),就用 module.exports。
不建议同时使用 exports 和 module.exports。
如果先使用 exports 对外暴露属性或方法,再使用 module.exports 暴露对象,会使得 exports
上暴露的属性或者方法失效。原因在于,exports 仅仅是 module.exports 的一个引用。
function require(...){
var module = {exports: {}};
((module, exports) => {
function myfn () {}
// 这个myfn就是我们自己的代码
exports.myfn = myfn; // 这里是在原本的对象上添加了一个myfn方法。
module.exports = myfn;// 这个直接把当初的对象进行覆盖。
})(module,module.exports)
return module.exports;
}
- require方法接受以下几种参数的传递:
1.http、fs、path等,原生模块。
2. ./mod或…/mod,相对路径的文件模块。
3. /pathtomodule/mod,绝对路径的文件模块。
4.mod,非原生模块的文件模块。
十六、路由
parse 解析
query 查询
全局变量
Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
当你定义一个全局变量时,这个变量同时也会成为全局对象的属性,反之亦然。需要注 意的是,在 Node.js 中你不可能在最外层定义变量,因为所有用户代码都是属于当前模块的, 而模块本身不是最外层上下文。
注意: 最好不要使用 var 定义变量以避免引入全局变量,因为全局变量会污染命名空间,提高代码的耦合风险。
- __filename
表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径。
// 输出全局变量 __filename 的值
console.log( __filename );
- __dirname
__dirname 表示当前执行脚本所在的目录。
常用工具
- util
util 是一个Node.js 核心模块,提供常用函数的集合,用于弥补核心 JavaScript 的功能 过于精简的不足。
文件系统模块 fs
Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。
异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。
建议大家使用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。
-fs 方法
/**
* 1打开文件
* 以下是在异步模式下打开文件语法格式
* fs.open(path,flags[,mode],callback)
* 参数
* path:文件路径
* flags:文件打开的行为
* mode:设置文件模式(权限),文件创建默认权限为0666(可读,可写)
* callback-回调函数,带有两个参数如:callback(err,fd)
*/
var fs = require('fs');
// 异步打开文件
console.log('准备打开文件');
fs.open('input.txt','r+',function(err,fd){
if(err){
return console.error(err);
}
console.log('文件打开成功!');
})
/**
* 2获取文件信息
* fs.stat(path,callback)
* 参数:
* callback:两个,err,stats,stats是fs.State的对象
* fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:
*
* isFile是文件
* isDirectory是否是目录
* isBlockDevice是块设备
* isCharacterDevice是字符设备
* isSymbolicLink是软链接
* isFIFO是FIFO
* isSocket是 Socket 返回 true
*/
fs.stat('input.txt',function(err,stats){
console.log(stats.isFile(),'是否是文件');
})
/**
* 3写入文件
* fs.writeFile(file, data[, options], callback)
*
* writeFile 直接打开文件默认是 w 模式,所以如果文件存在,该方法写入的内容会覆盖旧的文件内容!!!
* 参数
* file文件名或文件描述符
* data:要写入文件的数据,可以是string或buffer(缓冲对象
* options - 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 'w'
* callback - 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。
*/
console.log('准备写入文件')
fs.writeFile('input.txt','我是通过 fs.writeFile写入文件内容的',function(err){
if(err){
return console.error(err)
}
console.log('数据写入成功!')
console.log('---我是分界线---')
console.log('读取刚刚写入的新数据!')
fs.readFile('input.txt',function(err,data){
if(err){
return console.error(err);
}
console.log('异步读取文件数据:',data.toString())
})
})
/**
*4 异步读取文件
* fs.read(fd, buffer, offset, length, position, callback)
* fd - 通过 fs.open() 方法返回的文件描述符。
参数:
buffer - 数据写入的缓冲区。
offset - 缓冲区写入的写入偏移量。
length - 要从文件中读取的字节数。
position - 文件读取的起始位置,如果 position 的值为 null,则会从当前文件指针的位置读取。
callback - 回调函数,有三个参数err, bytesRead, buffer,err 为错误信息, bytesRead 表示读取的字节数,buffer 为缓冲区对象。
*/
var buf = new Buffer.alloc(1024);
console.log("准备打开已存在的文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功4444!");
console.log("准备读取文件4444:");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
console.log(bytes + " 字节被读取");
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
});
});
/**
*5 异步关闭文件
* fs.close(fd, callback)
* 该方法使用了文件描述符fd来读取文件。
* 参数
* fd - 通过 fs.open() 方法返回的文件描述符。
* callback - 回调函数,没有参数
*/
var fs = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开文件!");
fs.open('input.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("准备读取文件!");
fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功5555");
});
});
});
/**
* 6异步截取文件
* fs.ftruncate(fd,len,callback) 截取后破坏原文件
* 参数:
* fd - 通过 fs.open() 方法返回的文件描述符。
* len - 文件内容截取的长度。
* callback - 回调函数,没有参数。
*/
var fs5 = require("fs");
var buf = new Buffer.alloc(1024);
console.log("准备打开文件!");
fs5.open('input5.txt', 'r+', function(err, fd) {
if (err) {
return console.error(err);
}
console.log("文件打开成功!");
console.log("截取10字节内的文件内容,超出部分将被去除。");
// 截取文件
fs5.ftruncate(fd, 10, function(err){
if (err){
console.log(err);
}
console.log("文件截取成功。");
console.log("读取相同的文件");
fs5.read(fd, buf, 0, buf.length, 0, function(err, bytes){
if (err){
console.log(err);
}
// 仅输出读取的字节
if(bytes > 0){
console.log(buf.slice(0, bytes).toString());
}
// 关闭文件
fs5.close(fd, function(err){
if (err){
console.log(err);
}
console.log("文件关闭成功!");
});
});
});
});
/**
* 6删除文件
* fs.unlink(path, callback)
*/
console.log("准备删除文件!");
fs.unlink('xxx', function(err) {
if (err) {
return console.error(err,'333333');
}
console.log("文件删除成功!");
});
/**
* 7创建目录
* fs.mkdir(path[, options], callback)
* 参数
* path文件路径
* options 参数可以是:
recursive - 是否以递归的方式创建目录,默认为 false。
mode - 设置目录权限,默认为 0777。
*callback - 回调函数,没有参数。
*/
console.log('创建目录./test/ee')
// test目录必须存在
fs.mkdir('./test/ee',function(err){
if(err){
return console.error(err,'创建目录报错')
}
console.log('目录创建成功')
})
/**
* 8读取目录
* fs.readdir(path, callback)
* 略
* callback - 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表。
*/
console.log("查看 /test 目录");
fs.readdir("../nodejs/",function(err, files){
if (err) {
return console.error(err,'99999');
}
files.forEach( function (file){
console.log( file ,'文件目录 读取999');
});
});
/**
* 删除目录
* fs.rmdir(path, callback)
* callback没有参数
*
*/
fs.rmdir("./test/ee",function(err){
if (err) {
return console.error(err);
}
console.log("读取 /test 目录");
fs.readdir(".test/",function(err, files){
if (err) {
return console.error(err);
}
files.forEach( function (file){
console.log( file );
});
});
});
数据库
php
十七、express
Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 Web 应用,和丰富的 HTTP 工具。
使用 Express 可以快速地搭建一个完整功能的网站。
Express 框架核心特性:
可以设置中间件来响应 HTTP 请求。
定义了路由表用于执行不同的 HTTP 请求动作。
可以通过向模板传递参数来动态渲染 HTML 页面。