NodeJs基礎

一、HelloWorld

1.1 安裝nodemon工具

在編寫調試Node.js項目,修改代碼後,需要頻繁的手動close掉,然後再重新啓動,非常繁瑣。現在,我們可以使用nodemon這個工具,它的作用是監聽代碼文件的變動,當代碼改變之後,自動重啓。

安裝命令:

npm i nodemon -g

安裝完成後,在任意目錄下新建js文件,文件內容如下:

console.log('hello node.js');
console.log('hello java');
console.log('hello python');

執行命令:nodemon 文件路徑,執行結果如下所示:
在這裏插入圖片描述
以後修改了js文件後,不需要每次重新運行node命令,提高開發效率。

二、模塊使用

Nodejs內置一些模塊,這些模塊是nodejs本身提供,我們只需要在js文件中導入它們即可使用。下面簡單介紹幾個比較常用的模塊:File System、OS、HTTP模塊等。

資料地址:http://nodejs.cn/api/modules.html

2.1 文件模塊

在 Node.js 模塊系統中,每個文件都被視爲一個獨立的模塊。如果要使用模塊中導出的函數,那麼就需要先導入模塊。

下面使用fs模塊讀取文件的內容:

第一步:導入fs模塊;

const fs = require('fs')

第二步:調用模塊提供的函數;

// 以同步方式讀文件
const data = fs.readFileSync('./config.js');
console.log('文件內容:', data);

// 以異步方式讀文件
fs.readFile('./config.js', (data) => {
    console.log('文件內容:', data);
});

nodejs幾乎所有的api都提供了同步和異步的版本。在實際開發中建議使用異步方式。但是有時我們需要對多個異步操作的執行順序進行控制,這時我們可以把異步代碼同步化。

讓異步代碼同步化的幾種方式:

方式一:使用Promise;

const {promisify} = require('util')
// 將fs.readFile函數轉換成Promise
const readFile = promisify(fs.readFile)
readFile('./config.js').then(data => console.log(data))

在nodejs的10.0以後版本,可以使用fs模塊提供了promises對象,該對象也提供了readFile方法實現同步的讀文件操作。

const {promises} = require('fs')
promises.readFile('./config.js').then(data => console.log(data.toString()))

方式二:使用generator函數;

function readFile(path) {
    return new Promise((resolve, reject) => {
        const data = fs.readFile(path, (err, data) => {
            if (err) {
                reject(err)
            } else {
                resolve(data);
            }
        });
    })
}

function* test() {
    yield readFile('./config.js');
    yield readFile('./config2.js');
}

const tt = test();
tt.next().value.then(res => {
    console.log('config.js文件內容:', res.toString());
})
tt.next().value.then(res => {
    console.log('config2.js文件內容:', res.toString());
})

方式三:使用async和await;

function readFile(path) {
    return new Promise((resolve, reject) => {
        const data = fs.readFile(path, (err, data) => {
            if (err) {
                reject(err)
            } else {
                resolve(data);
            }
        });
    })
}

async function test() {
    const p1 = await readFile('./config.js');
    console.log('config.js文件內容:', p1.toString())
    const p2 = await readFile('./config2.js');
    console.log('config2.js文件內容:', p1.toString())
}

test();

上面程序會先讀去config.js文件內容,讀完後再讀取config2.js文件內容。

2.2 Buffer模塊

Buffer代表緩衝器,用於在 TCP 流、文件系統操作、以及其他上下文中與八位字節流進行交互。

Buffer實例類似於從 0 到 255 之間的整數數組,它是一個8字節大小的數組,可存儲二進制數據,但是以十六進制格式展示出來。Buffer 的大小在創建時確定,且無法更改。

Buffer 類在全局作用域中,因此無需使用 require(‘buffer’)。

創建Buffer的不同方式:

方式一:使用Buffer.alloc方法創建一個固定長度的Buffer;

const buf = Buffer.alloc(10)

方式二:把數組轉換成Buffer;

const buf = Buffer.from([11, 22, 33])

方式三:把字符串轉換成Buffer;

const buf = Buffer.from('hello world', 'utf-8')

Buffer提供了toString方法,用於讀取Buffer中的數據。

buf.toString('utf-8')

合併多個Buffer:

const buf1 = Buffer.from('hello ')
const buf2 = Buffer.from('world ')
const buf3 = Buffer.concat([buf1, buf2])
console.log(buf3.toString());

2.3 http模塊

Node.js 中的 HTTP 接口旨在支持傳統上難以使用的協議的許多特性。 特別是,大塊的、可能塊編碼的消息。 接口永遠不會緩衝整個請求或響應,用戶能夠流式傳輸數據。

http頭消息:

{ 
	'content-length': '123',
 	'content-type': 'text/plain',
  	'connection': 'keep-alive',
  	'host': 'mysite.com',
  	'accept': '*/*' 
}

爲了支持所有可能的 HTTP 應用程序,Node.js 的 HTTP API 都非常底層。 它僅進行流處理和消息解析。 它將消息解析爲消息頭和消息主體,但不會解析具體的消息頭或消息主體。

要使用 HTTP 服務器和客戶端,必須 require(‘http’)。

下面我們使用http模塊開發一個簡單版的web服務器。

第一步:創建一個js文件,導入http模塊以及其他相關模塊;

const http = require('http')
const fs = require('fs')
const path = require('path')

第二步:調用http接口的createServer方法,該方法用於創建一個Http服務端;

const server = http.createServer((req, res) => {
    console.log('url: ', req.url); // 輸出 /
    console.log('method: ', req.method); // 輸出 get
    // 向客戶端發送響應消息
    res.write('hello ');
    res.write('world ');
    res.write('nodejs ');
    res.end('java');
})

第三步:調用listen方法監聽某個端口;

server.listen(3000)

res.end()方法用於結束請求,否則客戶端會一直處於等待狀態。

2.4 流

流(stream)是 Node.js 中處理流式數據的抽象接口。 stream 模塊用於構建實現了流接口的對象。

Nodejs提供四種不同類型的流:

  • writable - 可寫入數據的流(例如 fs.createWriteStream())。
  • Readable - 可讀取數據的流(例如 fs.createReadStream())。
  • Duplex - 可讀又可寫的流(例如 net.Socket)。
  • Transform - 在讀寫過程中可以修改或轉換數據的 Duplex 流(例如 zlib.createDeflate())

下面使用stream來完成文件的讀寫操作:

const fs = require('fs')

const inStream = fs.createReadStream('./config.js')
const outStream = fs.createWriteStream('./config2.js')

inStream.pipe(outStream)

在服務端向客戶端輸出圖片:

if (req.headers.accept.indexOf('image/*') !== -1 && method === 'GET') {
	 fs.createReadStream(path.resolve('.' + url)).pipe(res)
}

上面程序代碼中的響應對象res其實也是一個輸出流。如果可以在pipe方法中直接把res作爲參數傳入。

三、express使用

Express 是一個保持最小規模的靈活的 Node.js Web 應用程序開發框架,爲 Web 和移動應用程序提供一組強大的功能。

express主要解決nodejs開發中的兩個主要問題:路由和請求流程控制。

3.1 如何使用express

第一步:安裝express;

npm i express

第二步:新建一個js文件,導入express模塊;

const express = require('express')

第三步:調用express函數,該函數返回一個對象;

const app = express()

第四步:調用對象方法處理請求;

第五步:調用對象的listen方法,指定要監聽的端口;

下面演示express工具的簡單用法:

const express = require('express')
const fs = require('fs')
const path = require('path')

// 創建express對象
const app = express()

app.get('/', (req, res) => {
    fs.readFile(path.resolve('./index.html'), (err, data) => {
        if (err) {
            res.statusCode = 500;
            res.end('server err!')
        } else {
            res.statusCode = 200 // 請求成功
            res.setHeader('content-type', 'text/html;charset=utf-8') 
            res.end(data)
        }
    })
})

app.listen(3000)

3.2 實現簡單版的express

第一步:新建一個js文件,導入需要用到的模塊;

const http = require('http')
const url = require('url')

第二步:定義一個數組變量,用於存儲所有路由;

let routers = [] // 路由列表

第三步:創建一個主類,定義get方法;

get(path, handler) {
    // 保存路由
    routers.push({path, method: 'get', handler})
}

第四步:定義listen方法;

listen(port) {
    http.createServer((req, res) => {
        // url.parse方法可以把req.url的各個部分分解出來
        let {pathname} = url.parse(req.url, true)
        // 判斷該pathname在路由列表中是否存在
        // 如果存在,在執行對應的handler函數
        routers.forEach(v => {
            if (v.path === pathname) {
                v.handler(req, res)
                return
            }
        })
    }).listen(port)
}

第五步:定義導出;

module.exports = function() {
    return new Application()
}
發佈了109 篇原創文章 · 獲贊 39 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章