day01

node简介

  1. Node.js是一个让JavaScript运行在服务器端的开发平台。

    node就是一个js的执行环境

  2. node 与其它后台语言的不同

    1. Node.js不是一种独立的语言,与PHP、JSP、Python、Perl、Ruby的“既是语言,也是平台”不同,Node.js的1. 使用JavaScript进行编程,运行在JavaScript引擎上(V8)。
    2. 与PHP、JSP等相比(PHP、JSP、.net都需要运行在服务器程序上,Apache、Naginx、Tomcat、IIS。),Node.js跳过了Apache、Naginx、IIS等HTTP服务器,它自己不用建设在任何服务器软件之上。
    3. Node.js没有web容器。

      URL是通过了Node的顶层路由设计,呈递某一个静态文件的。
  3. node特点:

    --所谓的特点,就是Node.js是如何解决服务器高性能瓶颈问题的

    1. 单线程

      在Java、PHP或者.net等服务器端语言中,会为每一个客户端连接创建一个新的线程。而每个线程需要耗费大约2MB内存。也就是说,理论上,一个8GB内存的服务器可以同时连接的最大用户数为4000个左右。

      Node.js不为每个客户连接创建一个新的线程,而仅仅使用一个线程。当有用户连接了,就触发一个内部事件,通过非阻塞I/O、事件驱动机制,让Node.js程序宏观上也是并行的。使用Node.js,一个8GB内存的服务器,可以同时处理超过4万用户的连接。

      另外,单线程的带来的好处,还有操作系统完全不再有线程创建、销毁的时间开销。

      坏处,就是一个用户造成了线程的崩溃,整个服务都崩溃了,其他人也崩溃了。
    2. 非阻塞I/O ( non-blocking I/O )

      阻塞模式下,一个线程只能处理一项任务,要想提高吞吐量必须通过多线程。而非阻塞模式下,一个线程永远在执行计算操作,这个线程的CPU核心利用率永远是100%。
    3. 事件驱动( event-driven )

      在Node中,客户端请求建立连接,提交数据等行为,会触发相应的事件。

      Node.js中所有的I/O都是异步的,回调函数,套回调函数。
    4. 适合开发什么?
      1. 善于I/O,不善于计算。

        因为Node.js最擅长的就是任务调度,如果你的业务有很多的CPU计算,实际上也相当于这个计算阻塞了这个单线程,就不适合Node开发。
      2. 当应用程序需要处理大量并发的I/O,而在向客户端发出响应之前,应用程序内部并不需要进行非常复杂的处理的时候,Node.js非常适合。
      3. Node.js也非常适合与web socket配合,开发长连接的实时交互应用程序。
      4. 比如:

        ● 用户表单收集

        ● 考试系统

        ● 聊天室

        ● 图文直播

http模块

  1. //require表示引包,引包就是引用自己的一个特殊功能
    //require的时候会执行一遍此文件,而且不管require几次只会执行一次。
    //后面有用户再访问不会再次执行、引用
    var http = require("http"); //创建服务器,参数是一个回调函数,表示如果有请求进来,要做什么
    var server = http.createServer(function(req,res){
    //req表示请求,request; res表示响应,response //设置HTTP头部,状态码是200,文件类型是html,字符集是utf8
    res.writeHead(200,{"Content-type":"text/html;charset=UTF-8"});
    res.end("哈哈哈哈,我买了一个iPhone" + (1+2+3) + "s");
    }); //运行服务器,监听3000端口(端口号可以任改)
    server.listen(3000,"127.0.0.1");

url模块

  1. req

    req.url 属性,表示用户的请求URL地址。所有的路由设计,都是通过req.url来实现的。
  2. 识别URL

    用到两个新模块,第一个就是querystring模块,第二个就是url模块
    querystring.parse('foo=bar&baz=qux&baz=quux&corge')
    // returns
    { foo: 'bar', baz: ['qux', 'quux'], corge: '' } // it can decode `gbk` encoding string
    querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null,
    { decodeURIComponent: gbkDecodeURIComponent })
    // returns
    { w: '中文', foo: 'bar' }
    //url.parse()可以将一个完整的URL地址,分为很多部分:
    //host、port、pathname、path、query var pathname = url.parse(req.url).pathname;
    //url.parse()如果第二个参数是true,则 query 属性会通过 querystring 模块的 parse() 方法生成一个对象
    //就可以直接打点得到这个参数
    var query = url.parse(req.url,true).query;
    var age = query.age; //直接打点得到这个参数

fs模块

  1. 事件循环机制
    var server = http.createServer(function(req,res){
    //不处理小图标
    if(req.url == "/favicon.ico"){return;} //给用户加一个五位数的id
    var userid = parseInt(Math.random() * 89999) + 10000; console.log("欢迎" + userid); res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});
    //两个参数,第一个是完整路径,当前目录写./
    //第二个参数,就是回调函数,表示文件读取成功之后,做的事情
    fs.readFile("./test/1.txt",function(err,data){ //异步执行,不会阻塞前后的代码
    if(err){ throw err; } console.log(userid + "文件读取完毕");
    res.end(data);
    });
    });
    // 并不一定是打印每一次 “欢迎..”间隔打印一次 “..文件读取完毕”
  2. API
    1. //创建文件夹
    fs.mkdir("./album/aaa"); 2. //stat检测状态,*异步执行*
    fs.stat("./album/bbb",function(err,stats){
    //检测这个路径,是不是一个文件夹
    console.log(stats.isDirectory());
    });
  3. 异步导致的错误
    失败案例,列出album文件夹中的所有子文件夹 
    
    3. //读取文件夹
    fs.readdir("./album",function(err,files){
    //files是个文件名的数组,表示./album这个文件夹里的所有东西(文件、文件夹) for(var i = 0 ; i < files.length ;i++){
    var thefilename = files[i];
    //进行一次检测
    fs.stat("./album/" + thefilename,function(err,stats){
    //由于异步,本次使用的 thefilename,并不一定是本次循环所赋的值 if(stats.isDirectory()){ //如果他是一个文件夹,那么输出它
    wenjianjia.push(thefilename);
    }
    console.log(wenjianjia); //由于异步不会真的打印所出有文件夹
    });
    }
    }); <!--循环里面放异步就容易出现这种错误-->

异步变成同步(迭代器)

  1. 遍历album里面的所有文件、文件夹

    fs.readdir("./album/",function(err,files){
    //files是一个存放文件(夹)名的数组
    var wenjianjia = []; //存放文件夹的数组 //迭代器就是强行把异步的函数,变成同步的函数
    // 1做完了,再做2;2做完了,再做3
    (function iterator(i){
    //结束遍历
    if(i == files.length){
    console.log(wenjianjia);
    return; //一定不能丢,否则结束不了会报错
    } var thefilename = files[i];
    fs.stat("./album/" + thefilename,function(err,stats){
    if(stats.isDirectory()){
    //如果是文件夹,那么放入数组。不是,什么也不做
    wenjianjia.push(thefilename);
    }
    iterator(i+1);
    });
    })(0);
    });

path

  1. 1. path.extname('index.html');
    // 返回: '.html'
    path.extname('index.coffee.md');
    // 返回: '.md' 2. path.normalize() 方法会规范化给定的 path,并解析 '..' 和 '.' 片段
    path.normalize('/foo/bar//baz/asdf/quux/..');
    // 返回: '/foo/bar/baz/asdf'

静态资源文件管理

  1. var http = require("http");
    var fs = require("fs");
    var url = require("url");
    var path = require("path"); var server = http.createServer(function(req,res){ //得到地址
    var pathname = url.parse(req.url).pathname;
    //判断此时用户输入的地址是文件夹地址还是文件地址
    //如果是文件夹地址,那么自动请求这个文件夹中的index.html
    if(pathname.indexOf(".") == -1){
    pathname += "/index.html";
    }
    //输入的网址是127.0.0.1/images/logo.png
    //实际请求的是./static/images/logo.png
    var fileURL = "./" + path.normalize("./static/" + pathname);
    //得到拓展名
    var extname = path.extname(pathname); //把文件读出来
    fs.readFile(fileURL,function(err,data){
    //读完之后做的事情
    if(err){
    //文件不存在
    res.writeHead(404,{"Content-Type":"text/html;charset=UTF8"})
    res.end("404,页面没有找到");
    }
    //读完之后做的事情
    getMime(extname,function(mime){
    res.writeHead(200,{"Content-Type":mime})
    res.end(data);
    });
    });
    }); server.listen(80,"127.0.0.1"); function getMime(extname,callback){
    //读取mime.json文件,得到JSON,根据extname key ,返回对应的value
    //读取文件,异步,异步,异步
    fs.readFile("./mime.json",function(err,data){
    if(err){
    throw Error("找不到mime.json文件!");
    return;
    }
    //转成JSON
    var mimeJSON = JSON.parse(data);
    var mime = mimeJSON[extname] || "text/plain";
    //执行回调函数,mime类型字符串,就是它的参数
    callback(mime);
    });
    }

day02

模块化

  1. -- 狭义的说,每一个JavaScript文件都是一个模块;而多个JavaScript文件之间可以相互require,他们共同实现了一个功能,他们整体对外,又称为一个广义上的模块。

  2. Node.js中,一个JavaScript文件中定义的变量、函数,都只在这个文件内部有效。

    当需要从此JS文件外部引用这些变量、函数时,必须使用exports对象进行暴露。使用者要用require()命令引用这个JS文件。

  3. 一个JavaScript文件,可以向外exports无数个变量、函数。但是require的时候,仅仅需要require这个JS文件一次。使用的它的变量、函数的时候,用点语法即可。所以,无形之中,增加了一个顶层命名空间。

  4. Node中,js文件和js文件,就是被一个个exportsrequire构建成为网状的。而不是靠html文件统一在一起的。

  5. 可以将一个JavaScript文件中,描述一个类。用

    module.export = 构造函数名的方式向外暴露一个类。

  6. 也就是说,js文件和js文件之间有两种合作的模式:

    1. 某一个js文件中,提供了函数,供别人使用。 只需要暴露函数就行了: exports.msg=msg;
    2. 某一个js文件,描述了一个类: module.exports = People;, 此时,People就被视为构造函数,可以用new来实例化了。

文件夹模块

  1. var foo = require("foo.js"); 没有写./, 所以不是一个相对路径。是一个特殊的路径那么Node.js将该文件视为node_modules目录下的一个文件。

  2. node_modules文件夹并不一定在同级目录里面,在任何直接祖先级目录中,都可以。甚至可以放到NODE_PATH环境变量的文件夹中。

    var bar = require("bar");
    //那么Node.js将会去寻找node_modules目录下的bar文件夹中的index.js去执行。
  3. 每一个模块文件夹中,推荐都写一个package.json文件,这个文件的名字不能改,必须放在模块的根目录里。node将自动读取里面的配置。有一个main项,就是入口文件:

    {
    "name": "kaoladebar",
    "version": "1.0.1",
    "main" : "app.js"
    }
  4. package.json

    "dependencies": {
    "silly-datetime": "^0.^1.0" //^ 表示固定
    },

路径

1. require()别的js文件的时候,将执行那个js文件。

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文件,推荐用绝对路径:

```
fs.readFile(__dirname + "/1.txt",function(err,data){
if(err) { throw err; }
console.log(data.toString());
});
``` ```
var b = require(“./test/b.js”); // './' 指当前文件路径 fs.readFile( "./uploads",function(err,data){ // './' 指根目录文件路径
...
});
```

body-parser、formidable

```
var bodyParser = require('body-parser'); app.use(bodyParser.urlencoded({ extended: false }));
app.post("/",function(req,res){
console.log(req.body);
});
```
```
var formidable = require('formidable'); var server = http.createServer(function(req,res){
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); //所有的文本域、单选框,都在fields存放;
console.log(files); //所有的文件域,files res.writeHead(200, {'content-type': 'text/plain'});
res.end("成功");
});
}
});
```

day03

express路由能力

var express = require("express");
var app = express(); //当用get请求访问一个网址的时候,做什么事情:
//所有的GET参数,?后面的都已经被忽略。锚点#也被忽略;你路由到/a,实际/a?id=2&sex=nan 也能被处理
app.get("/haha",function(req,res){
res.send("这是haha页面,哈哈哈哈哈哈");
});
。 //当用post访问一个网址的时候,做什么事情:
app.post("网址",function(req,res){ //互联网的网址,不分大小写 });
//如果想处理这个网址的任何method的请求,那么写all
app.all("/",function(){ }); //正则表达式可以被使用。正则表达式中,未知部分用圆括号分组,然后可以用req.params[0]、[1]得到。req.params类数组对象。
app.get(/^\/student\/([\d]{10})$/,function(req,res){
res.send("学生信息,学号" + req.params[0]); //req.params[0]指第一个小括号匹配到的内容
}); app.get("/student/:id/:name",function(req,res){
var id = req.params["id"]; // :后的内容自动加入到req.params中(类数组对象)
var name = req.params["name"]; var reg= /^[\d]{6}$/; //正则验证
if(reg.test(id)){
res.send(id);
}else{
res.send("请检查格式");
}
}); app.listen(3000);

express静态文件

var express = require("express");
var app = express(); app.use(express.static("./public")); app.get("/haha",function(req,res){
res.send("haha ");
}); app.listen(3000);

express与模版引擎配合

var express = require("express");
var app = express(); app.set("view engine","ejs"); //不需要再require('ejs')
app.set('views', './views'); //设置存放模版文件路径,默认就是views app.get("/",function(req,res){
res.render("haha",{
"news" :["我是小新闻啊","我也是啊","哈哈哈哈"]
});
}); app.listen(3000);

express中间件

  1. 如果我的get、post回调函数中,没有next参数,那么匹配上第一个路由,就不会往下匹配了。

    如果想往下匹配的话,那么需要写next();
    app.get("/",function(req,res,next){
    console.log("1");
    next();
    }); app.get("/",function(req,res){
    console.log("2");
    });
    //不会打印 2
  2. 下面两个路由,感觉没有关系,但是实际上冲突了,因为admin可以当做用户名 login可以当做id。
    app.get("/:username/:id",function(req,res){
    console.log("1");
    res.send("用户信息" + req.params.username);
    }); app.get("/admin/login",function(req,res){
    console.log("2");
    res.send("管理员登录");
    });

    解决1: 交换位置。也就是说,express中所有的路由(中间件)的顺序至关重要。匹配上第一个,就不会往下匹配了。所以具体的往上写,抽象的往下写。

    app.get("/admin/login",function(req,res){
    console.log("2");
    res.send("管理员登录");
    }); app.get("/:username/:id",function(req,res){
    console.log("1");
    res.send("用户信息" + req.params.username);
    });

    解决2: 路由get、post、use这些东西,就是中间件,中间件讲究顺序,匹配上第一个之后,就不会往后匹配了。next函数才能够继续往后匹配。

    app.get("/:username/:id",function(req,res,next){
    var username = req.params.username;
    //检索数据库,如果username不存在,那么next()
    if(检索数据库){
    console.log("1");
    res.send("用户信息");
    }else{
    next();
    }
    }); app.get("/admin/login",function(req,res){
    console.log("2");
    res.send("管理员登录");
    });

express - use

  1. app.use() 也是一个中间件。与get、post不同的是,他的网址不是精确匹配的,而是能够有小文件夹拓展的(子路径)。

    比如网址: http://127.0.0.1:3000/admin/aa/bb/cc/dd
    app.use("/admin",function(req,res){ 
    
        res.write(req.originalUrl + "\n");   // /admin/aa/bb/cc/dd
    res.write(req.baseUrl + "\n"); // /admin
    res.write(req.path + "\n"); // /aa/bb/cc/dd res.end("你好");
    });

    如果写一个 /

    //当你不写路径的时候,实际上就相当于"/",就是所有网址
    app.use(function(req,res,next){
    console.log(new Date());
    next();
    });

    app.use()就给了我们增加一些特定功能的便利场所。

    实际上app.use()的东西,基本上都从第三方能得到。

    app.use(haha);
    
    function haha(req,res,next){
    var filePath = req.originalUrl;
    //根据当前的网址,读取public文件夹中的文件
    fs.readFile("./public/" + filePath,function(err,data){
    if(err){ //文件不存在
    next();
    return;
    }
    res.send(data.toString());
    });
    } //静态服务
    app.use(express.static("./public"));
    // jingtai路由 下才会访问静态文件
    app.use("/jingtai",express.static("./public"));

ejs - render()、express - send()、原生 - end()

  1. 大多数情况下,渲染内容用res.render(),将会根据views中的模板文件进行渲染。

    如果不使用views文件夹,那么app.set("views","aaaa");

  2. 如果想写一个快速测试页,可以使用res.send()

    这个函数将根据内容,自动帮我们设置了Content-Type头部和200状态码。

  3. send()end()一样,只能用一次。

    和end不一样send()能够自动设置MIME类型。

  4. 如果想使用不同的状态码,可以:

    res.status(404).send('Sorry, we cannot find that!');

  5. 如果想使用不同的Content-Type,可以:

    res.set('Content-Type', 'text/html');

GET请求和POST请求的参数

  1. GET请求的参数在URL中,在原生Node中,需要使用url模块来识别参数字符串。在Express中,不需要使用url模块了。可以直接使用req.query对象。
  2. POST请求在express中不能直接获得,必须使用body-parser模块。使用后,将可以用req.body得到参数。但是如果表单中含有文件上传,那么还是需要使用formidable模块。

nodeCZBK-笔记1的更多相关文章

  1. git-简单流程(学习笔记)

    这是阅读廖雪峰的官方网站的笔记,用于自己以后回看 1.进入项目文件夹 初始化一个Git仓库,使用git init命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file ...

  2. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  3. SQL Server技术内幕笔记合集

    SQL Server技术内幕笔记合集 发这一篇文章主要是方便大家找到我的笔记入口,方便大家o(∩_∩)o Microsoft SQL Server 6.5 技术内幕 笔记http://www.cnbl ...

  4. PHP-自定义模板-学习笔记

    1.  开始 这几天,看了李炎恢老师的<PHP第二季度视频>中的“章节7:创建TPL自定义模板”,做一个学习笔记,通过绘制架构图.UML类图和思维导图,来对加深理解. 2.  整体架构图 ...

  5. PHP-会员登录与注册例子解析-学习笔记

    1.开始 最近开始学习李炎恢老师的<PHP第二季度视频>中的“章节5:使用OOP注册会员”,做一个学习笔记,通过绘制基本页面流程和UML类图,来对加深理解. 2.基本页面流程 3.通过UM ...

  6. NET Core-学习笔记(三)

    这里将要和大家分享的是学习总结第三篇:首先感慨一下这周跟随netcore官网学习是遇到的一些问题: a.官网的英文版教程使用的部分nuget包和我当时安装的最新包版本不一致,所以没法按照教材上给出的列 ...

  7. springMVC学习笔记--知识点总结1

    以下是学习springmvc框架时的笔记整理: 结果跳转方式 1.设置ModelAndView,根据view的名称,和视图渲染器跳转到指定的页面. 比如jsp的视图渲染器是如下配置的: <!-- ...

  8. 读书笔记汇总 - SQL必知必会(第4版)

    本系列记录并分享学习SQL的过程,主要内容为SQL的基础概念及练习过程. 书目信息 中文名:<SQL必知必会(第4版)> 英文名:<Sams Teach Yourself SQL i ...

  9. 2014年暑假c#学习笔记目录

    2014年暑假c#学习笔记 一.C#编程基础 1. c#编程基础之枚举 2. c#编程基础之函数可变参数 3. c#编程基础之字符串基础 4. c#编程基础之字符串函数 5.c#编程基础之ref.ou ...

  10. JAVA GUI编程学习笔记目录

    2014年暑假JAVA GUI编程学习笔记目录 1.JAVA之GUI编程概述 2.JAVA之GUI编程布局 3.JAVA之GUI编程Frame窗口 4.JAVA之GUI编程事件监听机制 5.JAVA之 ...

随机推荐

  1. 玩转 sublime3 第二弹 ES6环境

    安装node: node作为JS的运行环境必须安装 文件下载:https://nodejs.org/dist/v6.11.4/node-v6.11.4-x64.msi 备注:可以去官网 https:/ ...

  2. ESLint可共享配置发布,团队自定义ESLint规则新鲜出炉

    ESLint于2013年6月份推出,至今4个年头,最新版本v4.8.0.它是目前主流的用于Javascript和JSX代码规范检查的利器,很多大公司比如Airbnb和Google均有一套自己的Java ...

  3. js生成json数据

    <script src="~/static/js/jquery.min.js"></script><script type="text/ja ...

  4. java基本的要点

    我想告诉大家的不是什么java基本要点,只是对初学者的一点忠告,本人是从八维学校亲身经历过的学生,要想学好并且快速了解java,那你首先必须有英语底子,没有英语底子,几个单词都不会的,我觉得还是放弃学 ...

  5. nodejs后台集成富文本编辑器(ueditor)

    1 下载ueditor nodejs版本 2 复制public目录下面的文件 到项目静态资源public文件夹下 3 在项目根目录创建ueditor文件夹 要复制进来的内容为 4 在根目录的 uedi ...

  6. ASP.NET没有魔法——ASP.NET MVC 与数据库之EntityFramework配置与连接字符串

    前几篇文章中介绍了如何使用Entity Framework来操作数据库,但是对EF的配置.连接字符串的指定仍然存在一些疑问. 本章将对EF的配置进行介绍. EF可以通过两种方式来实现配置,分别是代码方 ...

  7. GBK和UTF8有什么区别

    GBK编码:是指中国的中文字符,其它它包含了简体中文与繁体中文字符,另外还有一种字符“gb2312”,这种字符仅能存储简体中文字符. UTF-8编码:它是一种全国家通过的一种编码,如果你的网站涉及到多 ...

  8. 国内为什么没有好的 Stack Overflow 的模仿者?,因为素质太低?没有分享精神?

    今天终于在下班前搞定一个技术问题,可以准时下班啦.当然又是通过StackOverflow找到的解决思路,所以下班路上和同事顺便聊起了它,两个资深老程序猿,还是有点感叹,中国的程序员群体人数应该不少,为 ...

  9. Java基础机试题

    package day8;import java.util.Scanner;/** * Java基础机试题 * @author:lyrand * */public class convert {   ...

  10. Python C++扩展

    Python C++扩展 前段时间看了一篇文章,http://blog.jobbole.com/78859/, 颇有感触,于是就结合自己工作中的知识作了一个简单的Python移动侦测:移动侦测的算法使 ...