Node(补充)

作者: 不要和我名字一样 | 来源:发表于2017-07-16 16:15 被阅读22次
    1、特点:单线程,非阻塞I/o,事件驱动
    • 单线程的好处,减少了内存开销,操作系统的内存换页。
      如果某一个事情,进入了,但是被I/O阻塞了,所以这个线程就阻塞了。
    • 非阻塞I/O, 不会傻等I/O语句结束,而会执行后面的语句。
      非阻塞就能解决问题了么?比如执行着小红的业务,执行过程中,小刚的I/O回调完成了,此时怎么办??
    • 事件机制,事件环,不管是新用户的请求,还是老用户的I/O完成,都将以事件方式加入事件环,等待调度。
    2、HTTP模块

    Node.js中,将很多的功能,划分为了一个个mudule,大陆的书翻译为模块;台湾的书,翻译为模组。这是因为,有一些程序需要使用fs功能(文件读取功能),有一些不用的,所以为了效率,你用啥,你就require啥。

    
    //这个案例简单讲解http模块
    //引用模块
    var http = require("http");
    
    //创建一个服务器,回调函数表示接收到请求之后做的事情
    var server = http.createServer(function(req,res){
        //req参数表示请求,res表示响应
        console.log("服务器接收到了请求" + req.url);
        res.end();
    });
    //监听端口
    server.listen(3000,"127.0.0.1");
    
    

    设置一个响应头:

    res.writeHead(200,{"Content-Type":"text/plain;charset=UTF8"});
    
    3、模块exports使用

    Node.js中,一个JavaScript文件中定义的变量、函数,都只在这个文件内部有效。当需要从此JS文件外部引用这些变量、函数时,必须使用exports对象进行暴露。使用者要用require()命令引用这个JS文件。

    foo.js文件中的代码:

        var msg = "你好";
        exports.msg = msg;
    
    

    msg这个变量,是一个js文件内部才有作用域的变量,如果别人想用这个变量,那么就要用exports进行暴露。

    使用者:

        var foo = require("./test/foo.js");
        console.log(foo.msg);
    

    使用者用foo来接收exports对象,也就是说,这里的foo变量,就是文件中的exports变量。
    js文件中,可以用exports暴露很多东西,比如函数、变量。

    var msg = "你好";
    var info = "呵呵";
    function showInfo(){
      console.log(info);
    }
    exports.msg = msg;
    exports.info = info;
    exports.showInfo = showInfo;
    

    在使用者中,只需要require一次。

    可以将一个JavaScript文件中,描述一个类。用module.export = 构造函数名;的方式向外暴露一个类。

    也就是说,js文件和js文件之间有两种合作的模式:
    1) 某一个js文件中,提供了函数,供别人使用。 只需要暴露函数就行了; exports.msg=msg;
    2) 某一个js文件,描述了一个类。 module.exports = People;

    4、模块
    • 如果在require命令中,这么写:
      var foo = require("foo.js"); //没有写./, 所以不是一个相对路径。是一个特殊的路径
      那么Node.js将该文件视为node_modules目录下的一个文件
    • node_modules文件夹并不一定在同级目录里面,在任何直接祖先级目录中,都可以。甚至可以放到NODE_PATH环境变量的文件夹中。这样做的好处稍后你将知道:分享项目的时候,不需要带着modules一起给别人。
    • 每一个模块文件夹中,推荐都写一个package.json文件,这个文件的名字不能改。node将自动读取里面的配置。有一个main项,就是入口文件:
    1   {
    2     "name": "kaoladebar",
    3     "version": "1.0.1",
    4     "main" : "app.js"
    5   }
    

    package.json文件,要放到模块文件夹的根目录去。

    5、路径
    • require()中的路径,是从当前这个js文件出发,找到别人。而fs是从命令提示符找到别人。例如,桌面上有一个a.js, test文件夹中有b.js、c.js、1.txt.
      a要引用b:
        var b = require(“./test/b.js”);
    

    b要引用c:

        var b = require(“./c.js”);
    

    但是,fs等其他的模块用到路径的时候,都是相对于cmd命令光标所在位置。所以,在b.js中想读1.txt文件,推荐用绝对路径:

    1   fs.readFile(__dirname + "/1.txt",function(err,data){
    2       if(err) { throw err; }
    3       console.log(data.toString());
    4   });
    
    6、post请求提交

    静态页面:form.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1/dopost" method="post">
        <p>
            姓名:<input type="text" name="name">
        </p>
        <p>
            性别:
            <input type="radio" name="sex" value="男">男
            <input type="radio" name="sex" value="女">女
        </p>
        <p>
            爱好:
            <input type="checkbox" name="hobby" value="足球">足球
            <input type="checkbox" name="hobby" value="睡觉">睡觉
            <input type="checkbox" name="hobby" value="吃饭">吃饭
        </p>
        <p>
            <input type="submit">
        </p>
    </form>
    </body>
    </html>
    

    服务端:form.js

    /**
     * Created by 黄森 on 2017/7/16.
     */
    var http = require("http");
    var querystring = require("querystring");
    
    var server = http.createServer(function (req, res) {
        //如果你的访问地址是这个,并且请求类型是post
        if (req.url == "/dopost" && req.method.toLowerCase() == "post") {
            var allData = '';
            //下面是post请求接收的一个公式
            //node为了追求极致,它是一个小段一个小段接收的。
            //接受了一小段,可能就给别人去服务了。防止一个过大的表单阻塞了整个进程
            req.addListener("data", function (chunk) {
                allData += chunk;
            });
            //全部传输完毕
            req.addListener("end", function () {
                var datastring = allData.toString();
                res.end('success');
                //将datastring转为一个对象
                var dataObj = querystring.parse(datastring);
                console.log(dataObj);
                console.log("姓名:" + dataObj.name);
                console.log("性别:" + dataObj.sex);
            })
        }
    });
    server.listen(80, "127.0.0.1");
    

    如果表单中有checkbox,那么将会转换成数组输出,再去遍历:

    提交表单 输出结果
    7、文件上传

    只要涉及文件上传,那么form标签要加一个属性:

    <form action="http://127.0.0.1/dopost" method="post" enctype="multipart/form-data">
    

    静态页面:form.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1/dopost" method="post" enctype="multipart/form-data">
        <p>
            姓名:<input type="text" name="name">
        </p>
        <p>
            性别:
            <input type="radio" name="sex" value="男">男
            <input type="radio" name="sex" value="女">女
        </p>
        <p>
            爱好:
            <input type="checkbox" name="hobby" value="足球">足球
            <input type="checkbox" name="hobby" value="睡觉">睡觉
            <input type="checkbox" name="hobby" value="吃饭">吃饭
        </p>
        <p>
            图片:
            <input type="file" name="tupian" />
        </p>
        <p>
            <input type="submit">
        </p>
    </form>
    </body>
    </html>
    

    服务端代码:upload.js

    /**
     * Created by 黄森 on 2017/7/16.
     */
    var http = require("http");
    var util = require("util");//工具模块
    var formidable = require('formidable');//文件上传模块
    
    var server = http.createServer(function (req, res) {
        //如果你的访问地址是这个,并且请求类型是post
        if (req.url == "/dopost" && req.method.toLowerCase() == "post") {
            //Creates a new incoming form.
            var form = new formidable.IncomingForm();
            //设置文件上传存放地址
            form.uploadDir = "./uploads";
            //执行里面的回调函数的时候,表单已经全部接收完毕了。
            form.parse(req, function(err, fields, files) {
                if(err){
                    throw err;
                }
                console.log(fields);
                console.log(files);
                console.log(util.inspect({fields: fields, files: files}));
                //所有的文本域、单选框,都在fields存放;
                //所有的文件域,files
                res.writeHead(200, {'content-type': 'text/plain'});
    
                res.end("成功");
            });
        }
    });
    server.listen(80, "127.0.0.1");
    

    在这里上传上去的图片是没有扩展名的,所以下面我们需要进行文件上传改名的操作:

    /**
     * Created by 黄森 on 2017/7/16.
     */
    var http = require("http");
    var util = require("util");
    var formidable = require('formidable');
    var fs = require("fs");
    var sd = require("silly-datetime");
    var path = require("path");
    
    var server = http.createServer(function (req, res) {
        //如果你的访问地址是这个,并且请求类型是post
        if (req.url == "/dopost" && req.method.toLowerCase() == "post") {
            //Creates a new incoming form.
            var form = new formidable.IncomingForm();
            //设置文件上传存放地址
            form.uploadDir = "./uploads";
            //执行里面的回调函数的时候,表单已经全部接收完毕了。
            form.parse(req, function (err, fields, files) {
                if (err) {
                    throw err;
                }
                // 时间
                var ttt = sd.format(new Date(), 'YYYYMMDDHHmmss');
                // 随机数
                var ran = parseInt(Math.random() * 89999 + 10000);
                // 扩展名
                var extname = path.extname(files.tupian.name);
    
                //执行改名
                var oldpath = __dirname + "/" + files.tupian.path;
                var newpath = __dirname + "/uploads/" + ttt + ran + extname;
    
                //改名
                fs.rename(oldpath,newpath,function (err) {
                    if(err){
                        throw Error("改名失败");
                    }
                    res.writeHead(200, {'content-type': 'text/plain'});
                    res.end("成功");
                });
                //所有的文本域、单选框,都在fields存放;
                //所有的文件域,files
                res.writeHead(200, {'content-type': 'text/plain'});
                res.end("成功");
            });
        }
    });
    server.listen(80, "127.0.0.1");
    

    相关文章

      网友评论

        本文标题:Node(补充)

        本文链接:https://www.haomeiwen.com/subject/lqzfcxtx.html