《Nodejs實戰》筆記二:Node編程基礎

1. 用回調處理一次性事件

作一個簡單的HTTP服務器, 實現幾個功能html

  1. 異步獲取JSON中的數據
  2. 異步獲取HTML模板
  3. 將JSON中的數據導入HTML模板中
  4. 將HTML網頁顯示在瀏覽器上
// 一個小例子. 
const http = require('http')
const fs = require('fs')

const getTitles = (res) => {
    fs.readFile(__dirname + '\\titles.json', (err, data) => {
        if (err) return hadError(err, res)
        getTemplate(JSON.parse(data.toString()), res)
    })
}

const getTemplate = (titles, res) => {
    fs.readFile(__dirname + '\\template.html', (err, data) => {
        if (err) return hadError(err, res)
        formatHTML(titles, data.toString(), res)
    })
}

const formatHTML = (titles, tmpl, res) => {
    const html = tmpl.replace('%', titles.join('</li><li>'))
    res.writeHead(200, {'Content-Type': 'text/html'})
    res.end(html)
}

const hadError = (err, res) => {
    console.error(err)
    res.end('Server Error')
}

http.createServer((req, res) => {
    if (req.url = '/') {
        getTitles(res)
    }
}).listen(8080, '127.0.0.1')

2. 用事件發射器(EventEmitter)處理重複性事件

事件發射器會觸發事件, 而且在那些事件被觸發時能處理它們.
好比HTTP服務器, TCP服務器和流. 都被作成了事件發射器json

事件是經過監聽器進行處理的.
監聽器是與事件相關聯, 每當有事件出現時, 就會被觸發的回調函數
例如Node中 TCP socket, 它有一個data事件, 每當socket有新數據的時候就會觸發瀏覽器

socket.on('data', handleData)

2.1 示例. 用on方法響應事件

const net = require('net')
const server = net.createServer((socket) => {
    socket.on('data', data => {
        console.log(data.toString())
        socket.write(data)
    })
})

server.listen(8888)

2.2 建立事件發射器

EventEmitter是一個事件發射器
咱們能夠經過EventEmitter的實例服務器

  1. 註冊監聽器異步

    eventEmitter.on()
  2. 觸發事件socket

    eventEmitter.emit()

所以, 寫出一個小demo函數

const EventEmitter = require('events').EventEmitter

const channel = new EventEmitter()
channel.on('join', () => { // 註冊監聽, 監聽join事件, 事件被觸發後調用後面的函數
    console.log('welcome!')
})

channel.emit('join') // 發射事件

注: 事件名稱能夠是任意字符串. 只有error事件是特殊的ui

2.3 使用事件發射器實現簡單的發佈/訂閱系統(聊天室)

const events = require('events')
const net = require('net')

const channel = new events.EventEmitter()
channel.clients = {}
channel.subscriptions = {}
channel.on('join', function(id, client) {
    console.log(`監聽到${id}號玩家加入遊戲`)
    this.clients[id] = client
    this.subscriptions[id] = (senderId, msg) => {
        if (id != senderId) {
            this.clients[id].write(msg)
            console.log(`${id}號玩家收到廣播消息${msg}`)
        }
    }
    this.on('boardcast', this.subscriptions[id])
})

let id = 0
const server = net.createServer((client) => {
    const gamer = ++id
    console.log(`玩家${gamer}進入服務器`)
    channel.emit('join', gamer, client)
    client.on('data', (data) => {
        console.log(`${gamer}玩家發送廣播消息: ${data.toString()} .`)
        channel.emit('boardcast', gamer, data.toString())
    })
})

server.listen(8888)

上面一版的代碼會出現問題, 由於咱們給每一個用戶都綁定了監聽器, 當用戶退出的時候, 監聽器沒有關閉, 就會出現錯誤this

因此咱們要在用戶退出的時候, 刪去與之對應的監聽器url

// ...
channel.on('leave', function(id) {
    console.log(`${id}號用戶已經退出房間`)
    channel.removeListener('broadcast', this.subscriptions[id])
})

// ...
let id = 0
const server = net.createServer((client) => {
    const user = ++id
    console.log(`用戶${user}進入服務器`)
    channel.emit('join', user, client)
    client.on('data', (data) => {
        console.log(`${user}用戶發送廣播消息: ${data.toString()} .`)
        channel.emit('broadcast', user, data.toString())
    })
    client.on('close', () => {
        channel.emit('leave', user)
    })
})
相關文章
相關標籤/搜索