node.js學習筆記

最近一直在學習node.js,因此總結了一些筆記,記錄在這裏。javascript

  • 模塊化和做用域
  • node中經常使用到的模塊
  • ffer
  • File
  • Http
  • stream

模塊化和做用域

this

瀏覽器中的this指的是window
node腳本文件中未定義時全局的this指向global ,定義時指的是module.exportshtml

a = 10
console.log(global.a) // 10
  • 全局做用域

沒用用var let const 定義的聲明的都是全局做用域java

  • 模塊做用域

使用變量修飾的都是模塊做用域node

  • 函數做用域
  • 塊級做用域

Buffer

處理二進制數據web

// 數組拼接buffer
var rs = require('fs').createReadStream('test.txt', { highWaterMark: 10 })
var data = []
rs.on('data', function (chunk) {
  data.push(chunk)
})
rs.on('end', function (chunk) {
  var buf = Buffer.concat(data)
  console.log(buf.toString())
})

File System

  • readFile

用來異步讀取文本文件中的內容,會將一個文件的所有內容都讀到內存中,適用於體積較小的文本文件;
讀取大文件,使用stream, readFileSync直接返回文本數據內容express

  • readFile 第一個參數是文件名,若是沒有回自動建立。
  • fs.stat 獲取文件的狀態

一般開發者能夠在調用open() read() 或者write方法以前調用fs.stat方法,用來判斷該文件是否存在。
fs.stat 和fs.fstat功能是同樣的,npm

區別是 fstat方法第一個參數是文件描述符,格式爲integer,fstat方法一般搭配open方法使用,由於open方法返回的結果就是一個文件描述。api

var fs= require('fs')
var data = fs.readFileSync('test.txt', {encoding: 'utf-8'})
console.log(data)


fs.writeFile('foo.txt', "hello world", {flag: 'a', encoding: 'utf-8'},
function (err) {
  if(err) {
    console.log(err)
    return
  } 
  console.log('success')
})
  • fs.stat
// 用來獲取文件的狀態 來判斷文件是否存在
// 常在調用open read witer是調用
fs.stat("foo.txt", function(err, result) {
  if(err) {
    console.log(err)
    return
  }
  console.log(result)
}) 

// fs.fstat

fs.open("foo.txt",'a',function(err,fd){
    if(err){
        console.log(err);
        return;
    }
    console.log(fd);
    fs.fstat(fd,function(err,result){
        if(err){
            console.log(err);
            return;
        }
        console.log(result);
    })
})
// 例子
// 獲取目錄下的說有文件名。
// fs.readdir 和fs.stat兩個api
var fs = require("fs");
function getAllFileFromPath(path) {
    fs.readdir(path, function (err, res) {
        for (var subPath of res) {
            var statObj = fs.statSync(path + "/" + subPath); //這裏使用了同步方法而非異步
            if (statObj.isDirectory()) {//判斷是否爲文件夾
                console.log("Dir:", subPath);
                getAllFileFromPath(path + "/" + subPath)//若是是文件夾,遞歸獲取子文件夾中的文件列表
            } else {
                console.log("File:", subPath);
            }
        }
    })
}
getAllFileFromPath(__dirname);

http

var http = require('http')
var server =http.createServer(function(req, res) {
  // 處理http請求
var method = req.method
var url = req.url
console.log(method, url)
  res.writeHead(200, {'content-type': 'text/plain'})
  res.end('hello  node!')
})
// 監聽來自客戶端的事件
server.on('connection', function(req, res) {
  console.log('connection')
})
server.on('request', function(req, res) {
  console.log('request')
})
server.listen(8080)

// 當訪問8080時,控制檯輸出 
// connected
// request
// request 打印兩次是由於其中一個是favicon.ico的請求
// 一個簡單的靜態服務器
var http = require('http')
var fs = require('fs')
var server = http.createServer(function (req, res) {

  if (req.url == '/') { //訪問8080
    var fileList = fs.readdirSync('./')
    res.writeHead(200, { 'content-type': 'text/plain' })
    // 將數組轉化爲字符串返回
    res.end(fileList.toString())
  } else {
    var path = req.url;
    // 在路徑字符串前加.表示當前目錄,避免在nix系統訪問/文件夾
    fs.readFile('.' + path, function (err, data) {
      if (err) {
        res.end('不存在')
        throw err;
      }
      res.writeHead(200, { 'content-type': 'text/plain' })
      res.end(data)
    })
  }

})
//1buffer.js,2http.js,3httpexmple.js,4.js,foo.txt,login.html,md.md,readFile.js,test.txt,this.js,upload.js
server.listen(8080)
// 處理異常
process.on('uncaughtException', function() {
  console.log('got error')
})

處理http請求

  • method url header

get post put delete update數組

// 處理http請求
var method = req.method
var url = req.url

Response 對象

上傳數據

  • upload.html
<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file"/>
    <br/>
    <input type="text" name="kind">
    <input type="submit" name="submit" value="submit"/>
</form>
  • js
// npm 安裝依賴  formidable 
var http = require('http')
var fs = require('fs')
var formidable = require("formidable");
var server = http.createServer(function (req, res) {
  if (req.url == '/upload') {
    switch (req.method) {
      case 'GET':
        fs.createReadStream('upload.html').pipe(res)
        break
      case 'POST':
        dealpost(req, res) // 自定義方法處理
        break
      default:
        console.log('other request')
    }
  } else {
    res.writeHead(302, {
      'Location': './upload'
    })
    res.end() // 將全部的url訪問都轉到/login路徑
  }
})

function dealpost(req, res) {
  var form = new formidable.IncomingForm();
  form.keepExtensions = true
  form.uploadDir = __dirname
  form.parse(req, function(err, fields, files) {
    if(err) {
      throw err
    }
    console.log(fields)
    console.log(files)
    res.writeHead(200, {'content-type': 'text/plain'})
    res.end('upload finished')
  })
}
server.listen(8080)

stream

stream 模塊是node操做流失數據瀏覽器

四種基礎的stream類型
  1. readable 可讀流
  2. writable 可寫流
  3. duplex 便可讀又可寫的流
  4. transform 操做寫入的數據,而後讀取結果,一般用於數據數據和輸出數據不要求匹配的場景,
var stream =require('stream')
var fs = require('fs')
var readStream = fs.createReadStream("./text.txt", 'utf-8')
readStream.on('data', function(data) {
  console.log(data)
})
readStream.on('close', function() {
  console.log('close')
})
readStream.on('error', function() {
  console.log('error')
})

當建立一個可讀流讀取一個較大的文件,在調用pipe方法將數據經過一個可寫流寫入另外一個位置。若是讀取的速度大於寫入的速度,那麼node將會在內存中緩存這些數據。

pipe 方法至關於在可讀流和可寫流之間加起來的橋樑,是的數據能夠經過管道由可讀流進入可寫流,

  • 使用pipe改寫的靜態文件服務器
var stream = require('stream')
var http = require('http')
var fs = require('fs')
var server = http.createServer(function (req, res) {
  if (req.url == '/') {
    var fileList = fs.readdirSync('./')
    res.writeHead(200, { 'Content-type': 'text/plain' })
    res.end(fileList.toString())
  } else {
    try {
      var readStream = fs.createReadStream(path).pipe(res);
    } catch (e) {
      res.end("file not exists");
    }
  }
})
server.listen(3000)
console.log("Listening on 3000");

//處理異常
process.on("uncaughtException", function () {
  console.log("got error");
})

// pipe方法接收一個writable對象,當readable對象調用pipe方法時,會在內部調用writable對象的write方法進行寫入。

Events

事件和監聽器

eventsnode程序中的對象會產生一系類的事件,他們被稱爲事件觸發器,

全部能觸發事件的對下你給都是eventEmitter類的實例。eventEmitter定義了on方法。

var eventEmitter = require("events");
var myEmitter = new eventEmitter();
myEmitter.on("begin",function(){
    console.log("begin");
})
myEmitter.emit("begin");

第五章

中間件middleware

  • 1 中間價的概念

express 自己是有路由和中間件構成的,從本質上來講,express的運行就是在不斷調用這個中間件。

中間件的本質上是接收請求而且作出相應動做的函數,該函數一般接收req和res做爲參數,以便對request和response對象進行操做,在web應用中,客戶端發起的每個請求,首先要通過中間件的處理才能繼續向下。

中間件的第三個參數通常寫做next,它表明一個方法,即下一個中間件。若是咱們在中間件的方法體中調用了next方法,即表示請求會通過下一個中間件處理。

  • 2中間件的功能

中間件是一個函數,能夠作到node代碼能作到的任何事情,除此以外還包括修改request和response對象、終結請求-響應循環,以及調用下一個中間件等功能,這一般是經過在內部調用next方法來實現的。若是某個中間件中沒有調用next方法,則表示對請求的處理到此爲止,下一個中間件不會被執行。

  • 中間件的加載

中間件的加載使用use方法來實現,改方法定義在express或者koa對象的實例上,

var app =express()
app.use(md)
  • express中的中間件

express應用可以使用以下幾種中間件

  • 應用級中間件
  • 路由級中間件
  • 錯誤處理中間件
  • 內置中間件
  • 第三方中間件
應用級中間件  使用app.use方法,綁定在app對象上的中間件
路由級中間件 路由處理是express的一部分,koa是經過第三方 koa-router
相關文章
相關標籤/搜索