Node.js

2019-07-07  本文已影响0人  彼得朱

1、终端基本使用

打开应用

常用命令

2、Node.js开发环境搭建

3、全局对象

4、回调函数

function sayHi() {
    console.log('Hi')
}

sayHi() // 调用函数

// 将匿名函数赋给变量
var sayBye = function (name) {
    console.log(name + ' Bye')
}

sayBye()

// 第一个参数是函数
function callFunction(fun, name) {
    fun(name)
}

callFunction(sayBye, 'able')
// 或者
callFunction(function (name) {
    console.log(name + ' Bye')
}, 'able')

5、模块化

传统非模块化开发有如下的缺点:

​ 1、命名冲突

​ 2、文件依赖

前端标准的模块化规范:

​ 1、AMD - requirejs

​ 2、CMD - seajs //阿里的

服务器端的模块化规范:

​ 1、CommonJS - Node.js

模块化相关的规则:

​ 1、如何定义模块:一个js文件就是一个模块,模块内部的成员都是相互独立

​ 2、模块成员的导出和引入

​ 模块成员的导出最终以module.exports为准

​ 如果要导出单个的成员或者比较少的成员,一般我们使用exports导出;

​ 如果要导出的成员比较多,一般我们使用module.exports的方式

​ 这两种方式不能同时使用

​ exports与module的关系:

​ module.exports = exports = {};

module 对象

//例1
//导出 03.js
var sum = function(a,b){
    return parseInt(a) + parseInt(b);
}
exports.sum = sum;
//引入
var module = require('./03.js');

var ret = module.sum(12,13);
console.log(ret);    //输出  25
//例2
//导出 03.js
var sum = function(a,b){
    return parseInt(a) + parseInt(b);
}
module.exports = sum;
// 引入
var module = require('./03.js');
var ret = module(12,13);
console.log(ret);   //输出  25
//例3
//导出
var flag = 123;
global.flag = flag;  

//引入
require('./07');
console.log(global.flag);   //输出 123
//例4
var counter = function(arr){
    return "There are" + arr.length +"element in the array";
}

var adder = function(a,b){
    return `the sum of the 2 numnber is ${a+b}`;
}

var pi = 3.14;

// module.exports.counter = counter;
// module.exports.adder = adder;
// module.exports.pi = pi;
// 或者
module.exports = {
    counter: counter,
    adder:adder,
    pi:pi
}

//引入
var stuff = require('./9');

console.log(stuff.counter(['1','2','3'])); //输出 There are3element in the array
console.log(stuff.adder(5,5));   //输出 the sum of the 2 numnber is 10
console.log(stuff.pi);  // 输出 3.14

注意:已经加载的模块会缓存。

​ 模块文件的后缀3种情况:.js .json .node

​ 上述三种模块的加载优先级(不加文件后缀时的优先级):.js -> .json -> .node

6、buffer基本操作

Buffer对象是Node处理二进制数据的一个接口。它是Node原生提供的全局对象,可以直接使用,不需要require(‘buffer’)。

7、事件(events)

//例1    
// 导入事件库
var events = require('events');

// 新建事件对象
var myEmitter = new events.EventEmitter();

// 绑定事件,事件名称叫做someEvent,后面是事件触发的回调函数
myEmitter.on('someEvent',function(message){
    console.log(message);
})
// 手动触发
myEmitter.emit('someEvent','the event was emmitted');  //the event was emmitted
//例2   (给对象一个事件)
var events = require('events');// 导入事件库
var util = require('util');    // 导入工具库

var Person = function(name){ //定义一个对象
    this.name = name;
}
// inherits是继承的意思,让Person类继承事件对象的属性
util.inherits(Person,events.EventEmitter);

// 定义三个对象
var xiaoming = new Person('xiaoming');
var lili = new Person('lili');
var lucy = new Person('lucy');

var persons = [xiaoming,lili,lucy];

// 循环数组,每个对象都绑定一个事件
persons.forEach(function(persons){
    persons.on('speak',function(message){
        console.log(persons.name +' said  '+ message);
    })
})
// 触发
xiaoming.emit('speak','hi');
lili.emit('speak','i want a apple');

// 注意,要让对象使用事件,就让对象继承那个事件库的对象就行了,也就是
// events.EventEmitter

8、读写文件(同步和异步)

//例1
var fs = require('fs');   //文件的一个库

var readMe = fs.readFileSync("readMe.txt","utf8");  //参数:文件名,编码
console.log(readMe);  // you read me!

fs.writeFileSync("writeMe.txt","这是写入的");  //参数:文件名,写入的东西
// 以上部分是同步执行情况
// node.js执行JavaScript的时候是单线程的,如果读写文件很耗时,他就会阻塞

注意:IO操作是很耗时的,它不能阻塞主线程,应该发起一个新的线程去执行它

​ noejs中异步处理操作,异步的操作都要加回调函数

//例2
// 解决办法,用异步
var fs = require('fs');

var readMe = fs.readFile("readMe.txt","utf8",function(err,data){
    console.log(data);     //you read me!
    fs.writeFile("writeMe.txt","写入的内容",function(){
        console.log('writeMe has finished!');
    })
})

console.log("finished");    //这个比上面那句先执行
// why
/*
    第二条语句是一个异步的事件,异步的IO操作,nodejs在执行JavaScript的时候
    是单线程的,语句还是一行一行往下执行,为什么这里会先执行最后一句呢?这是因为
    nodejs维护了一个事件队列,执行第二句的时候,会在事件队列那里注册一个事件,告诉
    这个事件队列我将要去读一个文件,但是这个回调函数没有被马上执行,这个操作是
    瞬间完成的。完成之后他就会执行主线程的第三个语句。当主线程空闲之后,它就会
    去找事件队列里面的事件,把它取出来,然后发起一个线程执行,执行成功后,它就
    告诉主线程我已经成功了,你来执行我吧。所以这里先执行的是主线程,然后执行的
    是异步操作里面的回调函数。

    注意:IO操作是很耗时的,它不能阻塞主线程,应该发起一个新的线程去执行它
          noejs中异步处理操作,异步的操作都要加回调函数
*/
 
//例3
var fs = require('fs');
// 异步删除文件
fs.unlink("writeMe.txt", function () {
    console.log("delete writeMe.txt file");
})

// 同步创建和删除目录
fs.mkdirSync('stuff');
fs.rmdirSync('stuff');

// 异步创建目录,但是这种递归回调,嵌套太多会出现问题,以后再说解决办法
fs.mkdir('stuff', function () {
    fs.readFile('readMe.txt','utf8',function(err,data){
        fs.writeFile('./stuff/writeMe.txt',data,function(){
            console.log('copy successfully');
        })
    })
});

9、流和管道

//例1
var fs = require('fs');
// 创建一个输入流
var myReadStream = fs.createReadStream(__dirname+'/readMe.txt');
// 流是一个事件的实例,拥有事件的一些特性,它可以绑定一些监听函数
myReadStream.on('data',function(chunk){
    console.log('new chunk received');  //new chunk received
    console.log(chunk);    //<Buffer 79 6f 75 20 72 65 61 64 20 6d 65 21>
})
// 性能提高的原因是文件分成buffer了
//例2
var fs = require('fs');
// 创建一个读的流
var myReadStream = fs.createReadStream(__dirname+'/readMe.txt');
//创建一个写入的流
var myWriteStream = fs.createWriteStream(__dirname+'/writeMe.txt');

//设置编码
myReadStream.setEncoding('utf8');

var data = ""
// 接收数据时用的监听函数
myReadStream.on('data',function(chunk){
    data += chunk;
    myWriteStream.write(chunk);//这里写入内容
})
//接受完数据之后用的
myReadStream.on('end',function(){
    console.log(data);
})
//例3
var fs = require('fs');
// 创建一个读的流
var myReadStream = fs.createReadStream(__dirname+'/readMe.txt');
//创建一个写入的流
var myWriteStream = fs.createWriteStream(__dirname+'/writeMe.txt');

var writeData = "hello world";

myWriteStream.write(writeData,'utf8');   //向文件中写入 "hello world"  
myWriteStream.end();
myWriteStream.on('finish',function(){
    console.log('finished');
})

以上三例是用流来写入或读出文件

//管道

var fs = require('fs');
// 创建一个读的流
var myReadStream = fs.createReadStream(__dirname+'/readMe.txt');
//创建一个写入的流
var myWriteStream = fs.createWriteStream(__dirname+'/writeMe.txt');

// 直接将 myReadStream内容 写入 myWriteStream
myReadStream.pipe(myWriteStream);
var crypto = require('crypto');  //加密
var fs = require('fs');
var zlib = require('zlib');   //压缩

var password = new Buffer(process.env.PASS || 'password');
var encryptStream = crypto.createCipher('aes-256-cbc',password);

var gzip = zlib.createGzip();
var readStream = fs.createReadStream(__dirname+"/readMe.txt");
var writeStream = fs.createWriteStream(__dirname+"/out.gz");

// 压缩
readStream
    .pipe(encryptStream)
    .pipe(gzip)
    .pipe(writeStream)
    .on('finish',function(){
        console.log('done');
    });
//解压缩
var crypto = require('crypto');  //加密
var fs = require('fs');
var zlib = require('zlib');   //解压缩

var password = new Buffer(process.env.PASS || 'password');
var decryptStream = crypto.createDeCipher('aes-256-cbc',password);

var gzip = zlib.createGunzip();
var readStream = fs.createReadStream(__dirname+"/out.gz");

// 解压缩
readStream
    .pipe(gzip)
    .pipe(decryptStream)
    .pipe(process.stdout)
    .on('finish',function(){
        console.log('done');
    });

10、http模块,web服务器

下面几个是响应一个纯文本给客户端

var http = require('http');

var server = http.createServer(function(request,response){
    console.log("Request received");
    response.writeHead(200,{'Content-Type':'text/plain'});
    response.write('Hello from out application');
    response.end();
})

server.listen(3000);
console.log('Server started on locahost port 3000');
1.png
2.png
//把上面的  server.listen(3000);改成下面这句
server.listen(3000,'127.0.0.1');
3.png
//改用 request 表达式
var http = require('http');

// request表达式
var onRequest = function(request,response){
    console.log("Request received");
    response.writeHead(200,{'Content-Type':'text/plain'});
    response.end('Hello from out application');
}

var server = http.createServer(onRequest);

server.listen(3000,'127.0.0.1');
console.log('Server started on locahost port 3000');

11、web服务器响应json

var http = require('http');

// request表达式
var onRequest = function(request,response){
    console.log("Request received");
    // 这里改为响应json的
    response.writeHead(200,{'Content-Type':'application/json'});
    var myObj = {
        name:'hfisdwc',
        job:'programmer',
        age:27
    }
    response.end(JSON.stringify(myObj));  //将对象转换成json字符串,写入response中
}

var server = http.createServer(onRequest);

server.listen(3000,'127.0.0.1');
console.log('Server started on locahost port 3000');
4.png

序列化:把它转成字符串 stringify

反序列化:把字符串转成对象 parse

12、web服务器响应HTML

var http = require('http');
var fs = require('fs');

// request表达式
var onRequest = function(request,response){
    console.log("Request received");
    // 这里改为响应html的
    response.writeHead(200,{'Content-Type':'text/html'});
    var myReadStream = fs.createReadStream(__dirname+'/index.html','utf8');
    myReadStream.pipe(response);
}

var server = http.createServer(onRequest);

server.listen(3000,'127.0.0.1');
console.log('Server started on locahost port 3000');

13、模块化思想组织代码

var http = require('http');
var fs = require('fs');

function startServer() {
    // request表达式
    var onRequest = function (request, response) {
        console.log("Request received");
        // 这里改为响应html的
        response.writeHead(200, {
            'Content-Type': 'text/html'
        });
        var myReadStream = fs.createReadStream(__dirname + '/index.html', 'utf8');
        myReadStream.pipe(response);
    }

    var server = http.createServer(onRequest);

    server.listen(3000, '127.0.0.1');
    console.log('Server started on locahost port 3000');
}

// 导出
exports.startServer = startServer;
//导入
var server = require('./server');
server.startServer();

14、web服务器路由

var http = require('http');
var fs = require('fs');

function startServer() {
    var onRequest = function (req, res) {
        console.log('request received ' + req.url)

        if (req.url === '/' || req.url === '/home') {
            res.writeHead(200, { 'Content-Type': 'text/html' })
            fs.createReadStream(__dirname + '/index.html', 'utf8').pipe(res)
        } else if (req.url === '/review') {
            res.writeHead(200, { 'Content-Type': 'text/html' })
            fs.createReadStream(__dirname + '/review.html', 'utf8').pipe(res)
        } else if (req.url === '/api/v1/records') {
            res.writeHead(200, { 'Content-Type': 'application/json' })
            var jsonObj = {
                name: 'able'
            }
            res.end(JSON.stringify(jsonObj))
        } else {
            res.writeHead(200, { 'Content-Type': 'text/html' })
            fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(res)
        }
    }
    var server = http.createServer(onRequest)
    server.listen(3000)
    console.log('server started on http://127.0.0.1:3000')
}

// 导出
exports.startServer = startServer;

重构上面的路由代码:

//server.js
var http = require('http')
var url = require('url')   //url库
var querystring = require('querystring')

function startServer(route, handle) {
    var onRequest = function (req, res) {
        console.log('request received ' + req.url)
        var pathname = url.parse(req.url,true).pathname

        var data = ""
        req.on("error", function (err) {
            console.error(err)
        }).on("data", function (chunk) {
            data += chunk
        }).on("end", function () {
            if (req.mothod === "POST") {
                if (data.length > 1e6) {
                    req.connection.destroy() // 如果数据很大,就断开
                }
                route(handle, pathname, res, querystring.parse(data))
            } else {
                var params = url.parse(req.url, true).query
                route(handle, pathname, res, params)
            }
        })
        // 或者
        // var data = []
        // data.push(chunk)
        // data = Buffer.concat(data).toString()

    }
    var server = http.createServer(onRequest)
    server.listen(3000)
    console.log('server started on http://127.0.0.1:3000')
}

module.exports.startServer = startServer
//router.js
fs = require('fs')

function route(handle, pathname, res, params) {
    console.log('Routing a request for ' + pathname)
    if (typeof handle[pathname] === 'function') {
        handle[pathname](res, params)
    } else {
        console.log('No handle for ' + pathname)
        res.writeHead(200, { 'Content-Type': 'text/html' })
        fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(res)
    }
}

module.exports.route = route
//handler.js
var fs = require('fs')

function home(res) {
    console.log('home')
    res.writeHead(200, { 'Content-Type': 'text/html' })
    fs.createReadStream(__dirname + '/index.html', 'utf8').pipe(res)
}

function review(res) {
    console.log('review')
    res.writeHead(200, { 'Content-Type': 'text/html' })
    fs.createReadStream(__dirname + '/review.html', 'utf8').pipe(res)
}

function api_records(res, params) {
    console.log('api_records')
    res.writeHead(200, { 'Content-Type': 'application/json' })
    res.end(JSON.stringify(params))
}

module.exports = {
    home: home,
    review: review,
    api_records: api_records
}
//app.js
var server = require('./server')
var router = require('./router')
var handler = require('./handler')

var handle = {}
// key是路径,值是处理函数
handle['/'] = handler.home
handle['/home'] = handler.home
handle['/review'] = handler.review
handle['/api/v1/records'] = handler.api_records

server.startServer(router.route, handle)

15、web服务器使用get或post请求发送数据

有两种方式:通过地址栏和表单

地址栏是用get方法,表单是post方法。因为地址栏的数据是暴露出去的,所以通常用于查询数据,而通过表单传递数据一般用于提交一些信息。

querystring - 查询字符串

// 接收请求数据,然后处理,查看request 类型
var data = ""
req.on("error", function (err) {
    console.error(err)
}).on("data", function (chunk) {
    data += chunk
}).on("end", function () {
    if (req.mothod === "POST") {
        if (data.length > 1e6) {
            req.connection.destroy() // 如果数据很大,就断开
        }
        route(handle, pathname, res, querystring.parse(data))
    } else {
        var params = url.parse(req.url, true).query
        route(handle, pathname, res, params)
    }
})
// 或者
// var data = []
// data.push(chunk)
// data = Buffer.concat(data).toString()

16、包管理器 npm

# Or alias it in .bashrc or .zshrc
echo '\n#alias for npm\nalias npm="npm --registry=https://registry.npm.taobao.org \
  --cache=$HOME/.npm/.cache/npm \
  --disturl=https://npm.taobao.org/dist \
  --userconfig=$HOME/.npmrc"' >> ~/.zshrc && source ~/.zshrc

17、package.json 文件

18、nodemon监控文件并重启服务

上一篇 下一篇

猜你喜欢

热点阅读