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. Merge Two Binary Trees

    Given two binary trees and imagine that when you put one of them to cover the other, some nodes of t ...

  2. Crossin-8-1;8-2课程记录

    打开文件:    open,注意打开文件的路径    读取结束需使用close读取文件:    read    readlines    readline    for in 重置光标位置:   se ...

  3. c# 【MVC】WebApi通过HttpClient来调用Web Api接口

    /// <summary> /// HttpClient实现Post请求(异步) /// </summary> static async void dooPost() { st ...

  4. DevOps之软件定义网络SDN

    唠叨话 关于德语噢屁事的知识点,仅提供专业性的精华汇总,具体知识点细节,参考教程网址,如需帮助,请留言. <软件定义网络SDN(Software Defined Network)> 关于软 ...

  5. IDEA Maven 三层架构 1、基本的Archetype 搭建

    JDK:1.8 Maven:3.3.9 三层架构:基于 SpringMVC 的 UI 层.业务逻辑层以及数据访问层 从对 Maven 的了解可以看出,三层架构的创建在于对文件夹的合理安排,他们通常是主 ...

  6. 【特效】jquery选项卡插件,页面多个选项卡统一调用

    把选项卡整合了一下,写成个插件,这样可以整个站,或整个页面有多个选项卡时,统一调用.代码的具体注意事项已经写进注释了.用于js获取元素的class名称必须有,选项卡本身的样式,另再取一个名字来设置(本 ...

  7. Pyhton编程(三)之Pycharm安装及运算符

    一:上节题目解答 1)使用while循环输出 1 2 3 4 5 6 8 9 10(注意:没有7) n=1while n<11: if n==7: pass //pass代码段指代空代码.. e ...

  8. MVC-HtmlHelper简单总结

    Asp.Net MVC - Htmlhelper 总结 HtmlHelper是一个返回Html字符串的方法.返回的字符串可以是任意类型.例如你可以使用HtmlHelper方法返回一个标准的html标签 ...

  9. (转)UML实践详细经典教程----用例图、顺序图、状态图、类图、包图、协作图

    原文链接:http://dn.codegear.com/article/31863 面向对象的问题的处理的关键是建模问题.建模可以把在复杂世界的许多重要的细节给抽象出.许多建模工具封装了UML(也就是 ...

  10. javascript倒计时调转页面

    <html><head><meta http-equiv="Content-Type" content="text/html; charse ...