Node.jsNode.jsNode.js专题

node.js学习之路二(基础)

2018-07-14  本文已影响6人  w如弈如意c

关于http

客户端和服务端交互示意图
http过程示意图2
1.网站的访问流程
网站访问第一步
2.node创建一个服务
let http = require('http')
let port = 8000
http.createServer((req, res) => {  // 监听函数,当请求到来时,会执行回调函数
    // req代表客户端,是一个可读流
    // res代表服务端,是一个可写流
    res.setHeader('Content-type', 'text/plain;charset=utf8')
    res.write('hello')
    // 调用end方法,结束响应
    res.end('你好') // node是utf8写入,这样直接写在浏览器会乱码,所以需要在上面声明请求头

}).listen(port, () => { 
    console.log(`服务开启成功,端口为${port}`)
})  // 如果不写端口号,就是默认本机,,注意尽量使用3000以上

3.在本地服务读写文件

let http = require('http')
let fs = require('fs')
let port = 8000
http.createServer((req, res) => { 
    //不写编码类型buffer类型会自动转换为字符串
    res.setHeader('Content-type', 'text/plain;charset=utf8')
    // 如果读的文件是html且html上也有utf8的话,不需要设置请求头也会正常解析中文
    fs.readFile('./1.txt', 'utf8', function(err, data) { 
        res.end(data)
    })
}).listen(port, () => { 
    console.log(`服务开启成功,端口为${port}`)
})

也可以通过流的方式,(pipe)对象简写

let http = require('http')
let fs = require('fs')
let port = 8000
http.createServer((req, res) => { 
    res.setHeader('Content-type', 'text/plain;charset=utf8')
    fs.createReadStream('1.txt').pipe(res)
}).listen(port, () => { 
    console.log(`服务开启成功,端口为${port}`)
})

查看请求路径

let http = require('http')
let fs = require('fs')
let url = require('url') // 把一个路径解析成一个对象
let port = 8000
http.createServer((req, res) => { 
    res.setHeader('Content-type', 'text/plain;charset=utf8')
    fs.createReadStream('1.txt').pipe(res)
    // 查看请求路径
    console.log(req.url)  // 这个包括了?号前和?号后的内容,如:/index.html?a=1
    // 查看真正的请求路由(url)
    let urlData = url.parse(req.url)
    // 解析出来的对象的query就是连接上的参数,一对象的形式呈现; pathname就是真正的路由
    console.log(urlData.pathname)
}).listen(port, () => { 
    console.log(`服务开启成功,端口为${port}`)
})

如下:如果访问的是'/',显示主页html,如果访问的是文件,将文件内容读取返回,如果访问的是文件夹,默认去找html文件,如果文件不存在,返回404

let http = require('http')
let fs = require('fs')
let url = require('url') // 把一个路径解析成一个对象
let path = require('path')
let port = 8000
http.createServer((req, res) => { 
    // 如下:如果访问的是'/',显示主页html,如果访问的是文件,将文件内容读取返回,如果访问的是文件夹,默认去找html文件,如果文件不存在,返回404
    let {pathname, query} = url.parse(req.url, true) // true的作用是将query转换成一个对象,pathname是带'/'
    fs.stat('.' + pathname, function(err, stats) {
        if(err) {
            res.statusCode = 404  // 找不到就是404
            res.end(`${pathname} not found`)
        } else if (stats.isFile) {
            // 是文件的情况(这里没写头)
            fs.createReadStream('.' + pathname).pipe()
        } else if (stats.isDirectory()) {
            // 如果是文件夹,默认查找index.html,'./'也是文件夹,获取到当前的路径和我的index.html进行拼接
            let p = path.join('.' + pathname, 'index.html')  // 拼出来读写的内容
            fs.createWriteStream(p).pipe(res)
        }
    })
}).listen(port, () => { 
    console.log(`服务开启成功,端口为${port}`)
})

上面还有一个问题,头文件没偶遇设置,如下设置:

let http = require('http')
let fs = require('fs')
let url = require('url') // 把一个路径解析成一个对象
let path = require('path')
let port = 8000
// 获取后缀
let mine = {
    '.js': 'application/javascript',
    '.css': 'text/css',
    './html': 'text/html'
}
http.createServer((req, res) => { 
    // 如下:如果访问的是'/',显示主页html,如果访问的是文件,将文件内容读取返回,如果访问的是文件夹,默认去找html文件,如果文件不存在,返回404
    let {pathname, query} = url.parse(req.url, true)
    fs.stat('.' + pathname, function(err, stats) {
        if(err) {
            res.statusCode = 404  // 找不到就是404
            res.end(`${pathname} not found`)
        } else if (stats.isFile) {
            // 这里可还能是js,css,html等,可以获取后缀,来确定类型
            let extName = pathname.match(/\.\w+$/)[0]   // 正则匹配后缀
            res.setHeader('Content-type', mine[extName] + ';charset=utf8')
            fs.createReadStream('.' + pathname).pipe()
        } else if (stats.isDirectory()) {
            // 这里头文件是html
            res.setHeader('Content-type', 'text/html;charset=utf8')
            let p = path.join('.' + pathname, 'index.html')
            fs.createWriteStream(p).pipe(res)
        }
    })
}).listen(port, () => { 
    console.log(`服务开启成功,端口为${port}`)
})

node中间件mime,也能实现类型转化:(替换上面setHeader部分)

let mime = require('mime')
mime.getType(pathname) + '

4.fetch方法(代替ajax,用法更灵活)

    fetch('/lock', {
        method: 'GET'
    }).then(function(res) {
        // 第一个回调是promise
        console.log(res.json())
    }).then(function(data) {
        // 第一个回调是promise的结果
        console.log(data)
    })

express初步学习

有了express之前手写的node能简化很多,下面简单实现

let express = require('express')
// 引用express模块,express是一个函数
let app = express() // express函数执行后,返回的是一个http的监听函数,就是http.createdServer函数
// 并在此函数上扩展了一个listen可以监听得端口
app.listen(8000, function() {
    console.log(123)
})

express的路由

let express = require('express')
let app = express()
app.listen(8000)
// app监听函数上扩展了很多方法,包括get,post,delete,put等
// app.方法名('路径名',fn)
// 从上到下匹配,如果匹配到了并且结束响应,就不会往下走了
//路径指的是pathname,没有?后面的内容
// express重点就是扩展req和res的属性
app.get('/signin', function(req, res) {
    res.setHeader('Content-type', 'text/html;charset=utf8')
    res.end('登录')
})
app.get('/signup', function(req, res) {
    res.setHeader('Content-type', 'text/html;charset=utf8')
    res.end('注册')
})
// 上面都不匹配,all表示所有的方法,'*'表示所有路径
app.all('*', function(req, res) {
    res.end('404')
})

exress扩展的一些req的属性

let express = require('express')
let app = express()
app.listen(8000)
// 想区分是查询一个用户还是查询所有用户
app.get('/user', function(req, res) {
    console.log(req.query.id)  // (express扩展的方法)
    console.log(req.url)  // 获取整个路径,包括?
    console.log(req.path)  // 路径没有?号 --(express扩展的方法)
    console.log(req.headers) // 请求头,所有都是小写
    console.log(req.method)  // 请求的方法,所有的方法都是大写
})

上面例子优化,,将差一个和所有的方法分开,?号的路径无法区分

let express = require('express')
let app = express()
app.listen(8000)

// 如果访问/user?id=1 查一个, /user查所有,但这样路径都是/user,还是拆分
// user/1表示差一个, /user查所有,这样写就能区分差多个还是查一个
app.get('/user', function(req, res) {
    res.end('select all')
})
// 表示id是占位符,必须要有,但是可以随机
// /user/1/wc => {id:1, name:wc} = params   一一对应的关系
app.get('/user/:id/:name', function(req, res) {
    res.end('select one: ' + req.params.id + req.params.name)
})

分别处理参数的方法

let express = require('express')
let app = express()
app.listen(8000)
// app.pram()有拦截功能,可实现参数操作和路由分离开
// 处理id
app.pram('id', function(req, res, next) {
    res.prams.id = `你的id是${req.prams.id}`
    next()   // 调用next()就可以向下匹配,如果在这里借宿了请求,就结束
})
// 处理name
app.pram('name', function(req, res, next) {
    res.prams.name = `你的name是${req.prams.name}`
    next()
})
app.get('/user/:id/:name', function(req, res) {
    // express设置头文件 
    res.Header('Content-type','text/plain;charset=utf8')
   res.end(`${res.prams.id}${res.prams.name}`)
})

中间件(middleWare)当我们访问到最终目标之前执行的内容
中间件的第一个功能, 可以进行权限判断

 // 第一个参数是路径,如果不写,会对所以请求路径都回执行
 let express = require('express')
 let app = express()
 app.listen(8000)
 app.use(function(req,res, next) {  // 不调用next不往下走
     console.log('步骤一')
     next()
 })
 app.use(function(req,res, next) {  // 不调用next不往下走,一旦在上面调用res.end(),下面就执行结果就白搭了
    console.log('步骤二')
    next()
 })
 app.get('/user, function(req, res) {
    res.Header('Content-type','text/plain;charset=utf8')
    res.end('结束')
 })

中间件的第二个功能就是可以对res和req属性扩充

 let express = require('express')
 let app = express()
 app.listen(8000)
 // 中间件的第一个功能, 可以进行权限判断 
// 对执行路径“/user”有效
 app.use("/user",function(req,res, next) {  // 不调用next不往下走
     console.log('步骤一')
     req.a = 'aaaa'
     next()
 })
// 虽所有执行路径都有效
 app.use(function(req,res, next) {  // 不调用next不往下走,一旦在上面调用res.end(),下面就执行结果就白搭了
    console.log('步骤二')
    res.b = 'bbbb'
    next()
 })
 app.get('/user, function(req, res) {
    res.Header('Content-type','text/plain;charset=utf8')
    console.log(req.a + res.b)
    res.end('结束')
 })
总结下中间件特点:

1.可以进行权限判断
2.可以对res和req属性扩充
3.第一个参数是路径,如果不写,会对所以请求路径都回执行
4.中间件要放在执行路径之前才会生效

有了中间间,我们就可以统一设置头文件了

 // 通过中间件设置头文件(利用中间件不设第一个参数就是默认全部的特点)
 app.get(function(req, res) {
     res.Header('Content-type','text/plain;charset=utf8')
     next()
 })
 
 app.get('/user', function(req, res) {
    console.log(req.a + res.b)
    res.end('结束')
 })
 app.get('/pssword', function(req, res) {
     console.log(req.a + res.b)
     res.end('结束')
 })

错误中间件:
错误中间件放在最后面,接受4个参数,比正常中间件多一个err,err位next()中的参数

let express = require('express')
 let app = express()
 app.listen(8000)
 // 中间件的第一个功能, 可以进行权限判断 
 // 第一个参数是路径,如果不写,会对所以请求路径都回执行
 
app.use('/pssword',function(req,res, next) {
    console.log('步骤二')
    res.b = 'bbbb'
    next('错误')
 })
 app.get('/user', function(req, res) {
    console.log(req.a + res.b)
    res.end('结束')
 })
 // 错误中间件
 app.get(function(err, req, res, next) {
    console.log(err)
 })


注:未完,待续

上一篇下一篇

猜你喜欢

热点阅读