node.js學(xué)習(xí)筆記

1 buffer

  • 不需要require 的全局變量
  • 讓node 使用二進(jìn)制數(shù)據(jù)操作
  • 不占用v8的內(nèi)存,可以使用node管理
  • 一般steam流使用,充當(dāng)緩存區(qū)域---文件讀寫
alloc

創(chuàng)建指定大小的buffer

let buffer = Buffer.alloc(10) // 10 字節(jié)
let unsafeUn  = Buffer.allocUnsafe(10) // 在垃圾回收后獲取了沒有清理干凈的垃圾鎖片
console.log(buffer)
console.log(unsafeUn)
let b1 = Buffer.from("1") // chatCodeAt() 49  form(s1,s2) s2=utf-8  31=2*16  1 + 1*16 0
console.log(b1)
let b2 = Buffer.from([1,2,"abc"]) // abc 無法觸發(fā) 
let b3 = Buffer.from([1,2,Buffer.from("abc")]) // 
let b4 = Buffer.from("中").toString()
console.log(b2)
console.log(b3)
console.log(b4)
allocUnsafe

創(chuàng)建指定大小的buffer(不安全)

from

接收數(shù)據(jù)創(chuàng)建buffer

buffer的靜態(tài)方法
// fill
let bf = Buffer.alloc(6)
bf.fill("123")
console.log(bf) // 結(jié)果 <Buffer 31 32 33 31 32 33> 默認(rèn)填滿
let bf1 = Buffer.alloc(6)
bf1.fill("123",1,4) //<Buffer 31 32 33 31 32 33> 從第一位開始到第4位置結(jié)束
console.log(bf1) 

// write
let bf = Buffer.alloc(6)
bf.write("123")
console.log(bf) //  結(jié)果 <Buffer 31 32 33 00 00 00> 不會(huì)默認(rèn)填滿
let bf2 = Buffer.alloc(6)
bf2.write("123",1,3) // <Buffer 00 31 32 33 00 00> 從第一位開始到第3位置結(jié)束
console.log(bf2)
// toString 轉(zhuǎn)換ask嗎到字符
console.log(bf2.toString())

write 和fill的區(qū)別是,fill主動(dòng)填滿內(nèi)存,write不會(huì)

slice像數(shù)組slice 實(shí)例

let bf = Buffer.from("DDD")
console.log(bf.slice(2,3).toString())

copy 實(shí)例方法

let bf1 = Buffer.alloc(6)
let bf2 = Buffer.from("拉鉤")
 bf2.copy(bf1,3,3,6) // 第一個(gè)3 值得是b2往左的偏移量,第2個(gè)是copy的起始位,6是結(jié)束位置
console.log(bf1.toString())
console.log(bf2.toString())

concat 靜態(tài)方法


let a = Buffer.from("111")
let b = Buffer.from("222")
console.log(Buffer.concat([a,b],5).toString()) // concat 將兩個(gè)buffer 合并, 5是限制長度

isBuffer 靜態(tài)方法

let a = Buffer.from("111")

console.log(Buffer.isBuffer(a))
module.export 和 export 的不同

module.export 和 export的地址是執(zhí)行一個(gè)地方

let name1 = "jack"
let getName = () => {
        return name1
    }
    // module.exports = {
    //     name1,
    //     getName
    // }


// 上面等于 exports.name1= name1
//         exports.getName= getName

// 但是不能把 exports={name:111},因?yàn)?exports.name1 = name1
exports.getName = getName

console.log(module, "modulePage")

module 對(duì)象數(shù)據(jù)

Module {
    id: '/Users/liukun/Desktop/node/common/module.js', // 當(dāng)前文件夾
    path: '/Users/liukun/Desktop/node/common', // 調(diào)用的位置
    exports: { name1: 'jack', getName: [Function: getName] }, // 導(dǎo)出
    parent: Module { // 父級(jí)
        id: '.',
        path: '/Users/liukun/Desktop/node/common',
        exports: {},
        parent: null,
        filename: '/Users/liukun/Desktop/node/common/index.js',
        loaded: false,
        children: [
            [Circular]
        ],
        paths: [
            '/Users/liukun/Desktop/node/common/node_modules',
            '/Users/liukun/Desktop/node/node_modules',
            '/Users/liukun/Desktop/node_modules',
            '/Users/liukun/node_modules',
            '/Users/node_modules',
            '/node_modules'
        ]
    },
    filename: '/Users/liukun/Desktop/node/common/module.js', // 文件名稱
    loaded: false,
    children: [], // require 的依賴
    paths: [ // node查找位置 以 .js .json .node 補(bǔ)足查找
        '/Users/liukun/Desktop/node/common/node_modules',
        '/Users/liukun/Desktop/node/node_modules',
        '/Users/liukun/Desktop/node_modules',
        '/Users/liukun/node_modules',
        '/Users/node_modules',
        '/node_modules'
    ]
}

require

  • 查詢文件系統(tǒng)(有可能查緩存)node查找位置 以 .js .json .node 補(bǔ)足查找
  • 加載所有文件js(字符串)---readfileSync
  • 執(zhí)行所有文件(字符串轉(zhuǎn)為js),然后包裝module.export 掛載內(nèi)容
如何執(zhí)行 字符串js
  • eval
let str = "console.log(1)"
eval(str)
  • new Function
let num = 1
new Function("num","console.log(num+1)")(num)
  • node的vm模塊
let fs = require("fs")
let vm = require("vm")
let content = fs.readFileSync("./rs.txt")
vm.runInThisContext(content)

node 事件隊(duì)列

  • timer 執(zhí)行settimeout
  • pendding callbacks 執(zhí)行系統(tǒng)操作的回調(diào)例如 tcp udp
  • ide,prapare 只在系統(tǒng)內(nèi)部使用
  • poll 執(zhí)行i/o相關(guān) 例如 文件讀寫
  • check 執(zhí)行setImmediate中的回調(diào)
  • close callbacks 執(zhí)行close相關(guān)事件
const { setImmediate } = require("timers")
setImmediate(() => {
    console.log("setInmmet")
})
setTimeout(() => {
    console.log("setTIme")
})
Promise.resolve().then(() => {
    console.log("promise")
})
console.log("start")
process.nextTick(() => {
    console.log("nextTick")
})

console.log("end")
// start
// end
// nextTick
// promise
// setTIme
// setInmmet

注意nextTIck 大于promise

node事件循環(huán)和瀏覽器的區(qū)別
  • node有6個(gè)事件
  • 瀏覽器只有宏偉任務(wù)
node事件循環(huán)的問題
setImmediate(() => {
    console.log("setImmediate")
})
setTimeout(() => {
    console.log("setTimeout")
})
image.png

會(huì)發(fā)現(xiàn)有時(shí)答案相反:原因setTimeout 后面的時(shí)間定時(shí)器的值不寫為0的時(shí)候照成的,有時(shí)候會(huì)對(duì)時(shí)間計(jì)算錯(cuò)誤
問題

const fs = require("fs")
fs.readFile("./a.txt", () => {
    setImmediate(() => {
        console.log("setImmediate")
    })
    setTimeout(() => {
        console.log("setTimeout")
    })
})
// setImmediate setTimeout

應(yīng)為在 執(zhí)行poll 的io隊(duì)列后會(huì)去執(zhí)行 chek 隊(duì)列的setImmediate 。按照隊(duì)列順序往下走

stream 流

  • readable 可讀流,能夠?qū)崿F(xiàn)數(shù)據(jù)的讀取
  • writeable 可寫流,能夠?qū)崿F(xiàn)數(shù)據(jù)的寫入
  • duplex 雙工流,可以實(shí)現(xiàn)數(shù)據(jù)的讀寫
  • transform 轉(zhuǎn)換流??梢詫?shí)現(xiàn)數(shù)據(jù)的讀寫,并且可以進(jìn)行轉(zhuǎn)換
    并且 stream 模塊 實(shí)現(xiàn)了4個(gè)具體抽象
    所有的stream 都繼承了EventEmitter
const fs = require("fs")
let rs = fs.createReadStream("./a.txt")
let ws = fs.createWriteStream("./b.txt")
rs.pipe(ws)
// 根據(jù)流生成了b.txt
Readable
const fs = require("fs")
let rs = fs.createReadStream("./a.txt")
// readStream
rs.pipe(process.stdout)
// print  :"stream read write pipe"%
Readable 的兩種模式
  • 暫存模式
    readale事件監(jiān)聽,會(huì)把數(shù)據(jù)直接放進(jìn)緩存中
  • 流動(dòng)模式
    data 事件,會(huì)直接讀取流的內(nèi)容,不需要進(jìn)入緩存查找
  const { Readable } =require("stream")
let source = ['ll','kk','nn']
class myReadable extends Readable {
    constructor(source){
        super()
        this.source = source
    }
    // 必須_read ,這樣才能重新read
    _read(){
        const data = this.source.shift()||null
        this.push(data)
    }
}
let Readablem = new myReadable(source)
Readablem.on("readable",()=>{
    while((data = Readablem.read())!=null){
        // 第一次會(huì)打印出來 ll kk ,因?yàn)?,ll 最開始就在緩存里
        console.log(data.toString())
    }
})
Readablem.on("data",(chunk)=>{
    console.log(chunk.toString(),"chunk")
})
writable
const { Writable }  = require("stream")
class myWritable extends Writable {
    constructor(){
        super()
    }
    _write(chunk,en,done){
        process.stdout.write(chunk.toString()+"---wirtable")
        process.nextTick(done)
    }
}
let myw = new myWritable()
myw.write("lllllkkkkk","utf-8",()=>{
    console.log("end")
})
duplex
const { Duplex } = require("stream")
class myDuplex extends Duplex {
    constructor(source){
        super()
        this.source = source
    }
    _read(){
        let data = this.source.shift()||null
        this.push(data)
    }
    _write(chunk,en,done){
        process.stdout.write(chunk.toString())
        process.nextTick(done)
    }
}
let myduplex  = new myDuplex(["a","b","c"])
myduplex.write("aaakkk",(chunk)=>{
    console.log(chunk,"wirite")
})
myduplex.on("data",(chunk)=>{
    console.log(chunk.toString(),"data")
})
transform
const { Transform } = require("stream")
class MytransForm extends Transform {
    constructor(){
        super()
    }
    _transform(chunk,en,next){
        this.push(chunk.toString().toUpperCase())
        next()
    }
}
let mytransfor = new MytransForm()
mytransfor.write("dddd")
mytransfor.on("data",(chunk)=>{
    console.log(chunk.toString(),"chunk") // DDDD
})

transform 中即可讀寫,而duplex 讀寫是分開的,不能相互影響

readStream
rs = fs.createReadStream("./a.txt",{
    flags:"r", // 讀
    encoding:null,// 壓縮
    fd:null ,// 文件索引
    mode:438 ,// 讀取文件權(quán)限
    autoClose:true,//是否自動(dòng)關(guān)閉
    start:0, //開始位置
    // end:3 , // 結(jié)束位置
    highWaterMark:1 // 單詞read 最多的值
})
// rs.on("readable",(chunk)=>{
    
//  while((data = rs.read())!=null){
//      console.log(data.toString(),"data")
//  }
// })
rs.on("data",(chunk)=>{
    console.log(chunk.toString())
    rs.pause() // 使用狀態(tài)暫停
    setTimeout(()=>{
        rs.resume() // 每隔一秒 使 steam 變的流動(dòng)
    },1000)
})
  • open
  • data
  • end
  • close
  • err
rs = fs.createReadStream("./a.txt",{
    flags:"r", // 讀
    encoding:null,// 壓縮
    fd:null ,// 文件索引
    mode:438 ,// 讀取文件權(quán)限
    autoClose:true,//是否自動(dòng)關(guān)閉
    start:0, //開始位置
    // end:3 , // 結(jié)束位置
    highWaterMark:1 // 單詞read 最多的值
})
// rs.on("readable",(chunk)=>{
    
//  while((data = rs.read())!=null){
//      console.log(data.toString(),"data")
//  }
// })
let bufferArr = []
rs.on("data",(chunk)=>{
    console.log(chunk.toString())
    bufferArr.push(chunk)
    rs.pause() // 使用狀態(tài)暫停
    setTimeout(()=>{
        rs.resume() // 每隔一秒 使 steam 變的流動(dòng)
    },1000)
})
rs.on("open",()=>{
    console.log("open")
})
rs.on("end",(chunk)=>{
    bufferArr.concat(chunk)
    console.log(bufferArr.toString(),"bufferArr")
    console.log("end")
})
rs.on("close",()=>{
    console.log("close")
})
rs.on("error",()=>{

})
/*
    open
0
1
2
3
4
5
6
7
8
9
0,1,2,3,4,5,6,7,8,9 bufferArr
end
close
writeSteam
ws = fs.createWriteStream('./wab.txt')
ws.write("dsss",()=>{
    console.log("write")
})
ws.on("open",()=>{
    console.log("open")
})
ws.on("close",()=>{
    console.log("close")
})
ws.end("end 終止,使得會(huì) close,但是end后不能在 write")
// ws.write("wri hou")
ws.on("error",(err)=>{
    console.log(err)
})
/*
    open
    write
    close
*/
wtrite 執(zhí)行流程
let ws = fs.createWriteStream("./wab.txt",{
    flag:"w",
    encoding:null,
    mode:438,
    fd:null,
    highWaterMark:4,
    autoClose:true

})
let flag = ws.write("1")
console.log(flag)
 flag = ws.write("2")
console.log(flag)
 flag = ws.write("3")
console.log(flag)
 flag = ws.write("3")
console.log(flag)
 flag = ws.write("3")
console.log(flag)
 flag = ws.write("3")
console.log(flag)

 flag = ws.write("3")
console.log(flag)

 flag = ws.write("3")
console.log(flag)
 /*
true
true
true
false
false
false
false
false
*/

highWaterMark:4,設(shè)置緩存為長度為4的,如果寫入的值大于內(nèi)存中的值flag 就為false。
緩存清空后 監(jiān)聽操作

ws.on("drain",()=>{
    console.log("緩存開")
})
分批寫入文件
const fs = require("fs")
let ws = fs.createWriteStream("fenpi.txt",{
    highWaterMark:1
})
let fleg = true
let source = "abcd"
let num = 0
function writeFp(mark) {
        fleg = mark||fleg
    while(fleg&&num!=source.length){
        fleg = ws.write("1")
        num+=1
    }
}
writeFp()
// 監(jiān)聽有緩存有數(shù)據(jù)時(shí)
ws.on("drain",()=>{
    writeFp(true)
})

pipe 可以幫我們實(shí)現(xiàn)

背亞機(jī)制
const fs = require("fs")
const rs = fs.createReadStream("./a.txt",{
   highWaterMark:4
})
const ws = fs.createWriteStream("./fenpi.txt")
let flag = false
rs.on("data",(chunk)=>{
   flag = ws.write(chunk)
   console.log(flag)
   if(!flag){
       rs.paused()
   }
})
ws.on("drain",()=>{
   rs.resume()
})
// 上面和下面一樣的機(jī)制
rs.pipe(ws)

http

服務(wù)器和 客戶端服務(wù)
server

const http = require("http")
const url = require("url")
const querystring = require("querystring")
const server = http.createServer((req,res)=>{
    // req ,res 繼承了steam
    const {pathname,query} = url.parse(req.url)
    console.log(querystring.parse(req.url),"querystring")
    console.log(pathname,"pathName")
    console.log(query,"query")
    let resList = []
    req.on("data",(chunk)=>{
        resList.push(chunk)
    })
    req.on("end",()=>{
        let data = Buffer.concat(resList).toString()
        console.log(data,"data")
        if(req.headers["content-type"]=="application/json"){
            let val = JSON.parse(data)
            val.qq = "1129557848"
            res.end(JSON.stringify(val))
        }
    })
})
server.listen(3039,()=>{
    console.log("服務(wù)啟動(dòng)")
})

client-server

const http = require("http")
let options={
    host:"localhost",
    path:"/home?a=1&b=1",
    port:3039,
    method:"GET",
    headers:{
        "Content-Type":"application/x-www-form-urlencoded"
    }
}
// let req = http.get(options,(res)=>{
//  console.log(res)
// })
// req.end("dddd")
let requestOption = {
    host:"localhost",
    port:3039,
    path:"/index?m=1&d=1",
    method:"POST",
    headers:{
        "Content-Type":"application/json"
    }
}
let requestReq = http.request(requestOption,(res)=>{
    // req ,res 繼承了steam

        let reslist = []
        res.on("data",(v)=>{
            reslist.push(v)
        })
        res.on("data",()=>{
            console.log(Buffer.concat(reslist).toString()
)       })
})
requestReq.end(JSON.stringify({a:1,b:2}))
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容