作者:烨竹
本文参考:
https://www.w3cschool.cn/nodejs/
https://nodejs.org/dist/latest-v8.x/docs/api/synopsis.html
http://www.runoob.com/nodejs/nodejs-install-setup.html
简介:Node.js是一个Javascript运行环境(runtime)。实际上它是对Google V8引擎进行了封装。V8引 擎执行Javascript的速度非常快,性能非常好。Node.js对一些特殊用例进行了优化,提供了替代的API,使得V8在非浏览器环境下运行得更好
使用Sublime 编译nodeJS
开启Sublime应用程式,接下来,选功能列 Tools/Build System/New Build System…
此时,会出现一个这样的档案 untitled.sublime-build 将内容修改成:
{
"cmd": ["C:/Program Files/nodejs/node.exe", "$file"]
}
并修改储存成NodeJS.sublime-build
测试:写一些js代码,保存,按Ctrl+B查看编译结果
node.js应用组成
1、引入 required 模块:我们可以使用 require 指令来载入 Node.js 模块。
2、创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
3、接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。
//引入required模块
var http = require('http');
http.createServer(function (request, response) {
// 发送 HTTP 头部
// HTTP 状态值: 200 : OK
// 内容类型: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});
// 发送响应数据 "Hello World"
response.end('Hello World\n');
}).listen(8888);
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
node server.js
Server running at http://127.0.0.1:8888/
模块
Node.js 有三大类的模块(module Types)
Core Modules (原生模块)
Local Modules (自建模块)
Third Party Modules (第三方模块)
Core Modules (原生模块)
载入Core Modules
var module = require(‘module_name’);
载入modules 的注意事项
var log = require('./utility');
nodeJS把整个utility资料夹,当成一个包,所以,它会自动在这个资料夹里去找package定义文件,预设为package.json,之后,再根据定义文件里的关键字main描述的档名,载入档案。所以解决方案为自行定义一个package.json放在此utility资料夹里
./untility/package.json
{
"name" : "log",
"main" : "./log.js"
}
本地自动化功能操作:(module_name)
[http](https://nodejs.org/api/http.html):它包含可以用来建立http server的一些类别,方法,及事件。
[url](https://nodejs.org/api/url.html):它包含可以解析url的一些方法。
[querystring](https://nodejs.org/api/querystring.html):它包含可以处理由client端传来querystring的一些方法。
[path](https://nodejs.org/api/path.html):它包含可以处理一些档案或资料夹路径的方法。
[fs](https://nodejs.org/api/fs.html):它包含档案的存取/操作的一些类别,方法及事件。
[util](https://nodejs.org/api/util.html):它包含一些可供程序者使用的效能函式。
自建模块
log.js(新建)
var log = {
info: function (info) {
console.log('Info: ' + info);
},
warning:function (warning) {
console.log('Warning: ' + warning);
},
error:function (error) {
console.log('Error: ' + error);
}
};
module.exports = log //這一部很重要,只要,模組(程式)要給別的模組(程式)使用,必須加這個!!
LogApp.js(使用)
var myLogModule = require('./Log.js');
myLogModule.info('Node.js started');
结果:
详解:Exports 物件(exports是一個物件,所以,我们可以直接分派 屬性,函式(方法)及物件给它)
属性
exports.SimpleMessage = 'Hello world';
//or
module.exports.SimpleMessage = 'Hello world';
使用函式
module.exports.log = function (msg) {
console.log(msg);
};
使用物件
module.exports = {
firstName: 'James',
lastName: 'Bond'
}
Exports 函式(直接分派一个匿名函式给exports)
module.exports = function (msg) {
console.log(msg);
};
Exports 类别化函式
module.exports = function (firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = function () {
return this.firstName + ' ' + this.lastName;
}
}
NMP管理
简单介绍
npm -v
npm install npm -g //更新nmp
npm help
区域安装(你可以在你的应用文件夹里,安装你想要的套件,)语法
npm install <package name> //注意这里要cd到要安装的文件夹
举例说明如下
C:\cs> npm install express
生成两个软件
当然,里头也包含了你所安装的express.js模组也在express资料夹内
全域安装语法
npm install -g express
更新套件
npm update <package name>
解除安装套件
npm uninstall <package name>
更多npm资讯
https://docs.npmjs.com/
Web Server
处理Http Request
http.createServer() 方法,包含Node.js 提供的request 及respones 二个参数。
request 物件可以用来得到一些从http server 发过来的请求,例如url、http header 及data。
response 物件则送出回应给Http 送来的请求
建立
// var http = require('http'); // 1 - 载入 Node.js 原生模组 http
// var server = http.createServer(function (request, response) { // 2 - 建立server
// // 在此处理 客戶端向 http server 发送过來的 req。
// });
// server.listen(5000); //3 - 进入此网站的监听 port, 就是 localhost:xxxx 的 xxxx
// console.log('Node.js web server at port 5000 is running..')
//
var http=require('http');
var server=http.createServer(function(req,res){
if(req.url=='/'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is Home Page.</body></html>');
res.end();
}else if(req.url=='/student'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is student Page.</body></html>');
res.end();
}else if(req.url=='/admin'){
res.writeHead(200,{'Content-Type':'text/html'});
res.write('<html><body>This is admin Page.</body></html>');
res.end();
}else
res.end('Invalid Request!');
});
server.listen(5000);
返回json
var http = require('http');
var server = http.createServer(function (req, res) {
if (req.url == '/') { //check the URL of the current request
res.writeHead(200, { 'Content-Type': 'application/json' });
res.write(JSON.stringify({ message: "Hello World"}));
res.end();
}
});
server.listen(5000);
console.log('Node.js web server at port 5000 is running..')
文件操作
Node.js的fs module ,是用来操作实体档案,可以同步或非同步存取档案系统操作。一般建议使用非同步存取档案,性能高、速度快、无阻塞
非同步读取档案语法
fs.readFile(fileName [,options], callback)
fileName: 档案的完整路径及档名,格式字串。
options: options 可能是一个物件或字串,包含"编码"及"flag"。这里预设的编码是utf8 , flag是"r"。
call back: 是带两个参数的function,err及file data,当我们执行readFile完成时, 要做的事, 例如: 回传file data
例子:
var fs = require('fs');
fs.readFile('TestFile.txt', function (err, data) {
if (err) throw err;
console.log(data.toString());
});
我们执行完读取档案操作,它会执行function,如果有错误,会回传错误;成功,会回传所读取的档案资料。如图:
同步读取档案
var fs = require('fs');
var data = fs.readFileSync('dummyfile.txt', 'utf8');
console.log(data);
写入文件(fs.writeFile() 写入档案,如果档案存在,会覆写原本档案资料;否则会自动新增档案并写入资料)
fs.writeFile(filename, data[, options], callback)
fileName:档案的完整路径及档名,格式字串。
● data:要写入的档案内容。
● options: options可能是一个物件或字串,包含"编码"及"flag"。这里预设的编码是utf8 , flag是"w"。
● call back:只带一个错误参数err的function,当我们执行writeFile完成时,要做的事。例如:写入成功的讯息显示;失败时,丢出err。
开启档案
fs.open(path, flags[, mode], callback)
path: 档案的完整路径及档名,格式字串。
flag: 用flag代表操作行为。可以参考下图!
mode: mode代表文件的权限,预设为0666代表可读可写。
call back: 是带两个参数的function,err及file data,当我们执行open完成时, 要做的事, 例如: 打开成功的讯息显示;失败时,丢出err。
开启读取档案
fs.read(fd, buffer, offset, length, position, callback)
fd: 透过fs.open() 方法返回的文件描述符。
buffer: 数据写入的缓冲区。
offset: 缓冲区写入的写入偏移量。
length: 要从文件中读取的字元数。
position: 文件读取的起始位置,如果position 的值为null,则会从当前文件游标的位置读取。
callback:回呼函式,有三个参数err, bytesRead, buffer。
err为错误讯息, bytesRead表示读取的字元数,buffer为缓冲区对象
关闭
fs.close(fd, callback)
fd:透过fs.open()方法返回的文件描述符。
call back:只带一个错误参数err的function,当我们执行close完成时,要做的事。例如:失败时,丢出err。
删除文件
fs.unlink(path, callback);删除存在的文件。
path:档案路径。
callback:只带一个错误参数err的function,当我们执行unlink完成时,要做的事。例如:删除成功的讯息显示;失败时,丢出err。
更多资讯:https://nodejs.org/dist/latest-v8.x/docs/api/readline.html
代码调试工具(主要推荐阮一峰介绍的调试工具)
Node.js 内建的debugger
1、进入command prompt 执行debugger
node inspect orfile.js
2、此时,可以看到程式进入debugging 模式。你可以看到>符号,指向目前debugging 的程式行
3、.我们可以再在debug>输入next (或n),debugging下一个程式区段
4、如果我们想要执行到下一个debugger; ,则在debug>输入 cont (或c)
设定中断点break-point
setBreakpoint(), sb() – 设定中断点于目前所在行数
setBreakpoint(line), sb(line) – 设定中断点给特定行数
setBreakpoint(‘fn()’), sb(…) – 设定中断点在函式的第一句
setBreakpoint(‘script.js’, 1), sb(…)– 设定中断点,在指定档名的第一行。(用于程式中有载入别的档案时)
clearBreakpoint(‘script.js’, 1), cb(…)– 清除中断点,在指定档名的第一行。(用于程式中有载入别的档案时)
watch, watchers
在debug过程中,想要查看一些资讯,例如,变数/参数…,可以用watch(“exp")
删除某项watch资讯,则,可用 unwatch(“exp")
常用的内建debug指令:
next, n执行至下一行。
cont, c继续执行并停在下一个debuggers;
step, s进入函式逐一除错。
out Step, o跳出函式的逐一除错。
watch加入表示式及变数至watch
watcher查看所有被加入的watch的值。
Pause暂停执行程式。
更多资讯:
http://www.ruanyifeng.com/blog/2018/03/node-debugger.html
https://nodejs.org/dist/latest-v8.x/docs/api/inspector.html
事件监听
自定触发及监听函式
Javascript 事件绑定通常使用addlistener,通常触发事件范围会有限,像通常使用的事件绑定,click, hover, focus, blur..
eventEmitter:自定义事件触发
事件名称可以任意取名,通常我们用驼峰式命名法,但也不限定
函式可以被附加在这个物件,当物件被执行时,触发这个函式,这些函式叫监听函式
// get the reference of EventEmitter class of events module
var events=require('events');
//create an object of EventEmitter class by using above reference.
var em=new events.EventEmitter();
//綁定事件函式
em.on('FirstEvent',function(data){
console.log('First subscriber:'+data);
});
//emit觸發事件
em.emit('FirstEvent','我已經進入了第一事件的監聽函式!');
上述例子,我们先建立一个events.EventEmitter 物件,叫做em,然后,我们再绑定事件处理函式用on(),最后用emit触发事件
addListener()的方法,去自订触发事件:
var emitter=require('events').EventEmitter;
var em=new emitter();
em.addListener('FirstEvent',function(data){
console.log('First Scriber: '+data);
});
em.on('SecondEvent',function(data){
console.log('Second Scriber:'+data);
});
em.emit('FirstEvent',"這是第一個監聽式!");
em.emit('SecondEvent',"這是第二個監聽式!");
有二种EventEmitter 使用上的常见模式:从函式return EventEmitter 物件;继承EventEmitter 类别
从函式回传EventEmitter物件(也就是emit可以写在function里)
var emitter=require('events').EventEmitter;
function LoopProcessor(num){
var e = new emitter();
setTimeout(function(){
for(var i=1;i<=num;i++){
e.emit('BeforeProcess',i);
console.log('Processing number : '+i);
e.emit('AfterProcess',i);
}
},2000);
return e;
}
var lp=LoopProcessor(3);
lp.on('BeforeProcess',function(data){
console.log('About to start the process for '+data);
});
lp.on('AfterProcess',function(data){
console.log('Completed processing '+data);
});
执行结果:
继承EventEmitter 类别(我们可以用util.inherits(),它是utility module的方法,所以,一开始就必须用require(‘util’)载入该模组)
var emitter = require('events').EventEmitter;
//繼承時, 需要用到的模組
var util = require('util');
function LoopProcessor(num) {
var me = this;
setTimeout(function () {
for (var i = 1; i <= num; i++) {
me.emit('BeforeProcess', i);
console.log('Processing number:' + i);
me.emit('AfterProcess', i);
}
}
, 2000)
return this;
}
//直接讓LoopProcessor 繼承 emitter 類別
util.inherits(LoopProcessor, emitter)
var lp = new LoopProcessor(3);
lp.on('BeforeProcess', function (data) {
console.log('About to start the process for ' + data);
});
lp.on('AfterProcess', function (data) {
console.log('Completed processing ' + data);
});