Node.js学习(Node.js基础)

 

 

1、开发环境搭建

v8引擎是作为解析JavaScript程序来运行的

nodejs是一个高性能的,第一个体现在他的JavaScript解析速度很快,v8引擎性能很高,第二个事件驱动和非阻塞

2、全局对象

window对象等等

计时器对象

setTimeout(() => {
    console.log("3 secends passed!");
}, 3000);
// 一次间隔
time = 0;
var timer = setInterval(() => {
    time+=2;
    console.log("2 secends passed");
    if(time > 6){
        clearInterval(timer);
    }
}, 2000);

当前路径、当前文件名字

console.log(__dirname);
/* 打印出当前所在的目录 */
console.log(__filename);
/* 输出当前文件所在目录+名字 */

 

3、回调函数

 函数定义

function sayHi(){
    console.log("hi");
}
var sayBye = function(){
    console.log("bye");
}
sayHi();
sayBye();
// 这两种效果是一样的

回调函数:

function sayHi(){
    console.log("hi");
}
function callBackFunction(fun){
    fun();
}
callBackFunction(sayHi);

 带参数的

function sayHi(name=""){
    console.log("hi" + name);
}
function callFunction(fun,name=""){
    fun(name);
}
callFunction(sayHi);
callFunction(sayHi,"linlinlin");

还可以将函数放在参数中写

function callFunction(fun,name){
    fun(name);
}
callFunction(function(name){
    console.log("hi" + name);
},"linlinlin");

 4、模块

第一种方法:

app.js

var stuff = require('./count');

console.log(stuff.counter(['ruby', 'node.js','react']));
console.log(stuff.adder(3,2));
console.log(stuff.pi);

count.js

var counter = function(arr){
    return "There are" + arr.length + "elements in the array";
}

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

var pi = 3.14;

module.exports.counter = counter;
module.exports.adder = adder;
module.exports.pi = pi;

第二种方法:

var counter = function(arr){
    return "There are" + arr.length + "elements in the array";
}

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

var pi = 3.14;

module.exports = {
    counter: counter,
    adder: adder,
    pi: pi
}

第二种方法的变种:

var pi = 3.14;

module.exports = {
    counter: function(arr){
        return "There are" + arr.length + "elements in the array";
    },
    adder: function(a, b){
        return `the sum of the 2 numbers is ${a+b}`;
    },
    pi: pi
}

 5、事件

(Node.js里面也有很多函数,就像jQuery中有很多函数一样,需要自己查阅API学习)

events事件:

var events = require('events');

var myEmitter = new events.EventEmitter();

myEmitter.on('myEventName', function(message){
    console.log(message);
});

myEmitter.emit('myEventName', 'my event was emitted!');

events和util是Node.js的核心库

var events = require('events');
var util = require('util');

var Person = function(name){
    this.name = name;
}

util.inherits(Person, events.EventEmitter);
/* Person类继承了events.EventEmitter的特性,可以使用它的方法了 */

var xiaoming = new Person('xiaoming');
var lili = new Person('lili');
var lucy = new Person('Lucy');

var person = [xiaoming,lili,lucy];

person.forEach(function(person){
    person.on('speak',function(message){
        console.log(person.name + " said: " + message);
    })
});
xiaoming.emit('speak', 'hi');
lucy.emit('speak', 'i want a curry!');

 6、读写文件

Node.js在执行JavaScript的时候是单线程的,但是Node.js并不是单线程的

同步读取:

var fs = require('fs');

var readMe = fs.readFileSync("readMe.txt", "utf8");/* 同步读取,执行完这一句再执行下一句语句 */

//fs.writeFileSync("writeMe.txt",readMe);

console.log(readMe);

console.log("finished");

 

异步读取:

var fs = require('fs');

var readMe = fs.readFile("readMe.txt", "utf8",function(err, data){
    console.log(data);
});
/* 异步读取,执行完这一句再执行下一句语句 */ /* 异步方法,异步事件, 异步I/O操作*/ /* 事件队列,在到第二行的时候注册一个事件,告诉队列要读一个事件,这个回调函数在现在喊没有被执行,当在主线程空闲的时候他就会找事件队列中的事件,把他取出来,再从线程池中发起一个线程执行个事件队列里面的事件 */ console.log("finished");

 

异步写文件:

var fs = require('fs');

var readMe = fs.readFile("readMe.txt", "utf8",function(err, data){
    fs.writeFile('writeMe.txt',data, function(){
        console.log('writeMe has finished');
    })
});
console.log("finished");

 8、流

读文件:

var fs = require('fs');
var myReadStream = fs.createReadStream(__dirname + '/readMe.txt', 'utf8');

myReadStream.on('data', function(chunk){
    console.log('new chunk received');
    console.log(chunk);
})
/* <Buffer 0d 0a 3c 21 64 6f 63 74 79 70 65 20 68 74 6d 6c 3e 0d 0a 3c 68 74 6d 6c 3e 0d 0a 3c 68 65 61 64
3e 0d 0a 09 3c 6d 65 74 61 20 63 68 61 72 73 65 74 3d ... >
new chunk received
<Buffer 20 20 20 20 20 20 20 3c 62 75 74 74 6f 6e 20 63 6c 61 73 73 3d 22 62 74 6e 20 62 74 6e 2d 73 6d
20 62 74 6e 2d 6c 69 6e 6b 20 62 74 6e 2d 69 63 6f 6e ... > 
缓冲区文本越多buffer越长(没加编码就这样,要在后面加个编码才能够正常显示)
对文件分段处理
*/

*****

var fs = require('fs');
var myReadStream = fs.createReadStream(__dirname + '/readMe.txt');

myReadStream.setEncoding('utf8');

var data111 = "";
myReadStream.on('data', function(chunk){
    data111 += chunk;
})
/* data是一个事件类型,end也是一个事件类型,data是读取数据的事件,end是读取文件结束的事件 */
myReadStream.on('end', function(){
    console.log(data111);
})

 

写文件:

var fs = require('fs');
var myReadStream = fs.createReadStream(__dirname + '/readMe.txt');
var myWriteStream = fs.createWriteStream(__dirname + '/writeMe.txt');
myReadStream.setEncoding('utf8');

var data111 = "";
myReadStream.on('data', function(chunk){
    // data111 += chunk;
    myWriteStream.write(chunk);
})
/* data是一个事件类型,end也是一个事件类型,data是读取数据的事件,end是读取文件结束的事件 */
myReadStream.on('end', function(){
    // console.log(data111);
})

*****

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');/* 这个地方的编码可以不写!!! */
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.setEncoding('utf8');

var data111 = "";
myReadStream.on('data', function(chunk){
    // data111 += chunk;
    myWriteStream.write(chunk);
    console.log("结束写文件");
    // 这里是分多次写的,看你文件的大小了
})
/* data是一个事件类型,end也是一个事件类型,data是读取数据的事件,end是读取文件结束的事件 */
myReadStream.on('end', function(){
    // console.log(data111);
    console.log("结束读文件");
    // 结束读文件是在最后进行的
})

console.log("看看是同步还是异步");
// 从这里就可以看出流也是异步进行的
View Code

 

 

管道

var fs = require('fs');
var myReadStream = fs.createReadStream(__dirname + '/readMe.txt');
var myWriteStream = fs.createWriteStream(__dirname + '/writeMe.txt');

/* 管道方法也能实现读写文件 */
myReadStream.pipe(myWriteStream);

 

  和ls命令很像

ls相当于readStream   | 相当于管道   grep .js相当于写的流  (我这里用的windows好像不可以使用grep这个命令(讲师的是用的ios系统))

例: ls | grep js | grep app

 

Web服务器

http

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);
//server.listen(3000, '127.0.0.1');
console.log('Server started on localhost port 3000');

 

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('Hello from out application');/* 这样相当于上面一句注释的语句 */
});

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

 

var http = require("http");

var onRequest = function(request, response){
    console.log('Request received');
    response.writeHead(200, {'Content-Type': 'text/plain'});/* 响应一个纯文本 */
    //response.write('Hello from out application');

    response.end('Hello from out application');/* 这句函数不加浏览器一直在转圈,我也是醉了。。。 */
}

var server = http.createServer(onRequest);

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

 

响应JSON

var http = require("http");

var onRequest = function(request, response){
    console.log('Request received');
    response.writeHead(200, {'Content-Type': 'application/json'});/* 响应一个纯文本 */
    
    var myObj = {
        name : "hfpp2012",
        job: "programmer",
        age:27
    }

    response.end(JSON.stringify(myObj));
    /* JSON.stringify功能:序列化(转成字符串)
       JSON.parse功能:反序列化函数 (转化成原来的形式)*/
}

var server = http.createServer(onRequest);

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

 

响应html

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

var onRequest = function(request, response){
    console.log('Request received');
    response.writeHead(200, {'Content-Type': 'text/html'});/* 响应一个html文件 */
    /* text/html响应一个html文件
       text/plain响应一个纯文本
       application/json响应json对象 */
    var myReadStream = fs.createReadStream(__dirname + '/index.html' , 'utf8');
    //var myReadStream = fs.createReadStream((__dirname + '/index.html'), 'utf8');
    //__dirname和index.html应该是一个参数的,我个人理解加上一对括号比较好。
    myReadStream.pipe(response);
}

var server = http.createServer(onRequest);

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

 

html文件index.html是当前目录下的一个html文件

 模块化管理代码:

json.js

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

function startServer(){
    var onRequest = function(request, response){
        console.log('Request received');
        response.writeHead(200, {'Content-Type': 'text/html'});/* 响应一个html文件 */
        /* text/html响应一个html文件
           text/plain响应一个纯文本
           application/json响应json对象 */
        var myReadStream = fs.createReadStream(__dirname + '/index.html' , 'utf8');
        //var myReadStream = fs.createReadStream((__dirname + '/index.html'), 'utf8');
        //__dirname和index.html应该是一个参数的,我个人理解加上一对括号比较好。
        myReadStream.pipe(response);
    }
    
    var server = http.createServer(onRequest);
    
    server.listen(3000);
    //server.listen(3000, '127.0.0.1');
    console.log('Server started on localhost port 3000');    
}

exports.startServer = startServer;

testJson.js

var server = require('./json');

server.startServer();

 

路由

根据不同的路由,响应不同的html(/html就是一个路由)

 (这里浏览器会默认请求一个没有写的资源就是 favico.ico,需要设置一下html文件或者在nodejs文件里写明才可以不请求这个资源)

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

var onRequest = function (request, response) {
    console.log('Request received' + request.url);
    console.log("1");
    if (request.url === '/' || request.url === '/home') {
        response.writeHead(200, { 'Content-Type': 'text/html' });
        fs.createReadStream(__dirname + '/index.html', 'utf8').pipe(response);
        console.log("2");
    } else if (request.url === '/review') {
        response.writeHead(200, { 'Content-Type': 'text/html' });
        fs.createReadStream(__dirname + '/review.html', 'utf8').pipe(response);
    } else if (request.url === '/json') {
        response.writeHead(200, { 'Content-Type': 'application/json' });
        var jsonObj = {
            name: "http23424",
            id: "1244123"
        }
        response.end(JSON.stringify(jsonObj));
    } else {
        response.writeHead(200, { 'Content-Type': 'text/html' });
        fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(response);
    }
    console.log("3");
}

var server = http.createServer(onRequest);

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

 

review.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge"> -->
    <link rel="icon" href="data:;base64,=">
    <!-- <link rel="SHORTCUT ICON" href="111(这里面的内容就是默认请求的,只要rel值里面带icon关键字好像就可以)"> -->
    <title>Document</title>
</head>
<body>
    review.html
</body>
</html>

 

模块化代码:

 app.js

var server = require('./server');
var router = require('./router');
var handler = require('./handler');

var handle = {};/* 空的集合 */
handle["/"] = handler.home;
handle["/home"] = handler.home;
handle["/review"] = handler.review;
handle["/json"] = handler.json;

server.startServer(router.route, handle);

 

server.js

function startServer(route, handle){
    var onRequest = function (request, response) {
        console.log('Request received' + request.url);
        route(handle, request.url, response);
    }
    
    var server = http.createServer(onRequest);
    
    server.listen(3000);
    //server.listen(3000, '127.0.0.1');
    console.log('Server started on localhost port 3000');        
}

module.exports.startServer = startServer;

 

handler.js

var fs = require('fs');

function home(response){
    response.writeHead(200, {'Content-Type': 'text/html'});
    fs.createReadStream(__dirname + '/index.html' , 'utf8').pipe(response);
    //console.log("handle.log处理中过程");
}

function review(response){
    response.writeHead(200, {'Content-Type': 'text/html'});
    fs.createReadStream(__dirname + '/review.html' , 'utf8').pipe(response);
    //console.log("handle.log处理中过程");
}

function json(response){
    response.writeHead(200, {'Content-Type':'application/json'});
    var jsonObj = {
        name: "http23424",
        id: "1244123"
    }
    response.end(JSON.stringify(jsonObj));
    //console.log("handle.log处理中过程");
}

module.exports = {
    home: home,
    review: review,
    json: json
}

 

router.js

var fs = require('fs');

function route(handle,pathname, response){
    console.log('Routing a request for' + pathname);
    console.log(typeof handle[pathname]);
    if(typeof handle[pathname] === 'function'){
        handle[pathname](response);
        console.log("处理完handle[pathname]");
        // fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(response);

        /* 这里这种处理方式就解决了一个问题:
            本来不修改html的header的时候,她会默认请求一个favico.ico,
            只要你修改了html中的那个icon的link语句,那么她就不会再请求favico.ico这个图标了,
            这里只判断的是你的handle里的name 
            
            这里试了一下不添加这条语句会怎么样:
            依然显示除了正确的页面,这里我认为是流的操作方式问题,从网上查阅资料得知,
            这条请求时浏览器自己发的请求,
            之前的错误想法:所以在我们的代码里是不会处理这个请求的,这就解释了为什么
            命令行里有请求而浏览器却没有404页面。
            
            又一次错误想法:后面我仔细思考了一下,我们是在加载完review.html文件之后才有的这个多余的favicon.ico请求,
            所以这应该是在这个if的函数内执行的时候发出的请求,这个请求被监听到了,但是并不能够到达
            else的函数内

            正确的理解:我终于懂了,请求favicon.ico时如果请求不到东西那么是给favicon返回的response所以无论怎么弄
            都不会影响review页面的html内容。。。。。。。。。。。。。。。。。。。
            */
    }else{
        response.writeHead(200, {'Content-Type': 'text/html'});
        fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(response);
        console.log("处理完404页面测试,但是没有404页面");
    }
}

module.exports.route = route;

review.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge"> -->
    <!-- <link rel="icon" href="data:;base64,="> -->
    <!-- <link rel="SHORTCUT ICON" href="111(这里面的内容就是默认请求的,只要rel值里面带icon关键字好像就可以)"> -->
    <title>Document</title>
</head>
<body>
    review.html
</body>
</html>

404.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="icon" href="data:;base64,=">
    <title>Document</title>
</head>
<body>
    404.html
</body>
</html>
View Code

json.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="icon" href="data:;base64,=">
    <title>Document</title>
</head>
<body>
    json.html
</body>
</html>
View Code

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="icon" href="data:;base64,=">
    <title>Document</title>
</head>
<body>
    <div>
        index html
    </div>
</body>
</html>
View Code

使用get或post方法的实例

一般查询用get方法

一般提交一些表单等一些敏感数据使用post的方法

 

app.js(不进行修改)

var server = require('./server');
var router = require('./router');
var handler = require('./handler');


var handle = {};/* 空的集合 */
handle["/"] = handler.home;
handle["/home"] = handler.home;
handle["/review"] = handler.review;
handle["/json"] = handler.json;

server.startServer(router.route, handle);
View Code

server.js

var http = require("http");
var fs = require('fs');
var url = require('url');
/* url库对url进行一些处理,是url的工具库 */
var querystring = require('querystring');
function startServer(route, handle) {
    var onRequest = function (request, response) {
        var pathname = url.parse(request.url).pathname;/* 请求不包含?后面内容的路由 */
        console.log('Request received' + pathname);
        // var params = url.parse(request.url, true).query;
        // /* 传递一个使用get方法传递的数据,使用&符号连接多个数据
        //    true参数返回一个json类型的数据
        //    false参数返回一个字符串类型的数据 */
        // route(handle, pathname, response, params);
        var data = "";
        request.on("error", function (err) {
            //request也是一个继承事件的实例,request是一个流,流就是继承了事件的
            console.log(err);
        }).on("data", function (chunk) {
            // 上面的data是一个事件参数,下面的data是一个变量
            data += chunk;
        }).on("end", function () {
            if (request.method === "POST") {
                route(handle, pathname, response, querystring.parse(data));
            } else {
                var params = url.parse(request.url, true).query;
                /* 传递一个使用get方法传递的数据,使用&符号连接多个数据
                   true参数返回一个json类型的数据
                   false参数返回一个字符串类型的数据 */
                route(handle, pathname, response, params);
                /* http://localhost:3000/json?name=lin&age=22这样写就会返回一个json类型的字符串 */
            }
        })

    }

    var server = http.createServer(onRequest);

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

module.exports.startServer = startServer;

router.js

var fs = require('fs');

function route(handle,pathname, response, params){
    console.log('Routing a request for' + pathname);
    console.log(typeof handle[pathname]);
    if(typeof handle[pathname] === 'function'){
        handle[pathname](response, params);
        console.log("处理完handle[pathname]");
    }else{
        response.writeHead(200, {'Content-Type': 'text/html'});
        fs.createReadStream(__dirname + '/404.html', 'utf8').pipe(response);
        console.log("处理完404页面测试,但是没有404页面");
    }
}

module.exports.route = route;

handler

var fs = require('fs');

function home(response){
    response.writeHead(200, {'Content-Type': 'text/html'});
    fs.createReadStream(__dirname + '/index.html' , 'utf8').pipe(response);
    //console.log("handle.log处理中过程");
}

function review(response){
    response.writeHead(200, {'Content-Type': 'text/html'});
    fs.createReadStream(__dirname + '/review.html' , 'utf8').pipe(response);
    //console.log("handle.log处理中过程");
}

function json(response,params){
    response.writeHead(200, {'Content-Type':'application/json'});
    response.end(JSON.stringify(params));
}

module.exports = {
    home: home,
    review: review,
    json: json
}

 

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="icon" href="data:;base64,=">
    <title>Document</title>
</head>
<body>
    <form action="/json" method="POST">
        name: <input type="text" name="name"> age: <input type="text" name="age" />
        <input type="submit" value="提交">
    </form>
</body>
</html>

 

官方文档中给出的data的处理方法:

server.js

var http = require("http");
var fs = require('fs');
var url = require('url');
var querystring = require('querystring');
function startServer(route, handle) {
    var onRequest = function (request, response) {
        var pathname = url.parse(request.url).pathname;
        console.log('Request received' + pathname);
        //var data = "";
        var data = [];  //官方文档中的写法
        request.on("error", function (err) {
            console.log(err);
        }).on("data", function (chunk) {
            data.push(chunk);
        }).on("end", function () {
            if (request.method === "POST") {
                data = Buffer.concat(data).toString();  //官方文档中的写法(这样也是正确的,就不具体测试了)
                route(handle, pathname, response, querystring.parse(data));
            } else {
                var params = url.parse(request.url, true).query;
                route(handle, pathname, response, params);
            }
        })

    }

    var server = http.createServer(onRequest);

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

module.exports.startServer = startServer;

 

npm包管理器

www.npmjs.com

使用npm可以多种别人已经写好的框架,express框架等等非常强大的框架

npm.taobao.org用来安装国内淘宝的镜像源

 安装单命令时,全局安装加 -g参数,将其安装为一个可执行命令,作为一个可执行文件安装到我们的系统中

yarn命令也是一个和npm功能很像的命令,也有很多功能

package.json

 记录项目安装过哪些包

不需要node_modules目录的内容的,只需要安装过哪些包就可以了。

npm init初始化一个项目,生成一个package.json文件

scripts里面是脚本

npm run start(比如里面写一个入口文件)

直接使用npm install 就可以安装package里面的dependencies了

 

nodemon

每次修改文件之后就不用重启服务器了,nodemon这个插件实现了每次修改文件之后就会重启服务器了

安装nodemon使用全局安装,npm install -g nodemon

运行的时候就不用node project了,而是使用nodemon project

 

posted @ 2018-12-25 15:55  林丶  阅读(440)  评论(0编辑  收藏  举报