課程地址:javascript
http://www.javashuo.com/tag/進擊Node.js基礎(一)css
進擊Node.js基礎(二)html
1. nodejs建立服務器java
var http = require('http'); //加載http模塊 //請求進來時, 告訴服務器作什麼, 因而給createServer傳遞一個匿名回調函數. //兩個參數, 前面是請求體, 後面是響應體. 請求體用來獲取請求相應信息,好比請求ip地址,請求的類型get/post,res用來返回響應 http.createServer(function(req, res) { res.writeHead(200, {'Content-Type': 'text/palin'}); res.end('Hello World\n'); }).listen(1337, '127.0.0.1'); //經過listen使服務器在1337端口監聽請求 console.log('Server running at https://127.0.0.1:1337/');
2. nodejs安裝:node
一開始直接使用sudo apt-get install node後, 安裝好的node不能啓動且node -v也沒有輸出. node.js的版本號是v0.10.25.可是用npm安裝一些包時候卻說node版本不夠, 沒搞明白node和nodejs區別在哪裏.linux
因而卸載掉從nodejs.org上下了新版, 是node v6.10.0. 解壓後, 直接在那個目錄下能夠啓動node, 在網上查了使用了一個連接, 分別把node 和 npm設置了全局:數據庫
sudo ln -s /media/hao/3b6b3418-c087-4836-a75d-6d7a6023e495/Programs/node-v6.10.0-linux-x64/bin/node /usr/sbin/node
sudo ln -s /media/hao/3b6b3418-c087-4836-a75d-6d7a6023e495/Programs/node-v6.10.0-linux-x64/bin/npm /usr/sbin/npm
能夠用了.npm
關於nodejs和node版本的區別,參考這個帖子吧: nodejs各版本的區別api
3. 模塊: 從這裏開始都是慕課網老師Scott進擊NodeJS基礎(一)(二)課程的筆記數組
teacher.js
exports.add = function(){ }
var teacher = require('./teacher.js')
teacher.add('Scott')
4. nodejs中一些api
url.resolve
querystring
var http = require('http') var cheerio = require('cheerio') //npm install cheerio var url = 'http://www.imooc.com/learn/348' function filterChapters(html){ var $ = cheerio.load(html) var chapters = $('.chapter') // [{ // chapterTitle: '', // videos: [ // title:'', // id: '' // ] // }] var courseData = [] chapters.each(function(item){ var chapter = $(this) var chapterTitle = chapter.find('strong').text().trim('\n').split('\n')[0] var videos = chapter.find('.video').children('li') var chapterData = { chapterTitle: chapterTitle, videos: [] } videos.each(function(item){ var video = $(this).find(".J-media-item") var videoTitle = video.text().split(/\s+/).slice(1,-2).join(' ') var id = video.attr('href').split('video/')[1] chapterData.videos.push({ title: videoTitle, id: id }) }) courseData.push(chapterData) }) return courseData } function printCourseInfo(courseData){ courseData.forEach(function(item){ var chapterTitle = item.chapterTitle console.log(chapterTitle + '\n') item.videos.forEach(function(video){ console.log(' [' + video.id + ']' + video.title + '\n') }) }) } http.get(url, function(res) { var html = '' res.on('data', function(data){ html += data }) res.on('end', function(){ var courseData = filterChapters(html) printCourseInfo(courseData) }) }).on('error', function(){ console.log('獲取課程數據錯誤') })
6. 事件監聽的一個小例子
var EventEmitter = require('events').EventEmitter var life = new EventEmitter() //addEventListener life.setMaxListeners(6) //設置事件最大監聽數 默認爲10. 超出這個數目會報警告 life.on('求安慰', function(who){ console.log('給 ' + who + ' 倒水') }) life.on('求安慰', function(who){ console.log('給 ' + who + ' ...1') }) life.on('求安慰', function(who){ console.log('給 ' + who + ' ...2') }) life.on('求安慰', function(who){ console.log('給 ' + who + ' ...3') }) life.on('求安慰', function(who){ console.log('給 ' + who + ' ...4') }) life.on('求安慰', function(who){ console.log('給 ' + who + ' ...5') }) life.on('求安慰', function(who){ console.log('給 ' + who + ' ...6') }) var hasBeenListener = life.emit('求安慰', '槓子') //會返回值, 看是否被監聽過 //要移除函數, 不可以使用匿名函數, 只能移除具名函數 console.log(life.listeners('求安慰').length) //查詢監聽事件數 console.log(EventEmitter.listenerCount(life, '求安慰')) life.removeAllListeners('求安慰') life.emit('求安慰','gangzi')
7. Promise.js imooc
<!DOCTYPE html> <html> <head> <title>Promise animation</title> <style type="text/css"> .ball{ width: 40px; height: 40px; border-radius: 20px; } .ball1 { background: red;} .ball2 { background: yellow;} .ball3 { background: green;} </style> <script type="text/javascript" src="/home/hao/node_modules/bluebird/js/browser/bluebird.js"></script> </head> <body> <div class="ball ball1" style="margin-left: 0;"></div> <div class="ball ball2" style="margin-left: 0;"></div> <div class="ball ball3" style="margin-left: 0;"></div> </body> <script type="text/javascript"> var ball1 = document.querySelector('.ball1') var ball2 = document.querySelector('.ball2') var ball3 = document.querySelector('.ball3') function animate(ball, distance, cb){ setTimeout(function(){ var marginLeft = parseInt(ball.style.marginLeft, 10) if(marginLeft === distance){ cb && cb() } else { if(marginLeft < distance){ marginLeft++ } else { marginLeft-- } ball.style.marginLeft = marginLeft + 'px' animate(ball,distance,cb) } },13); } // animate(ball1, 100, function(){ // animate(ball2, 200, function() { // animate(ball3, 300, function(){ // animate(ball3, 150, function(){ // animate(ball2, 150, function(){ // animate(ball1, 150, function(){ // }) // }) // }) // }) // }) // }) var Promise = window.Promise function promiseAnimate(ball, distance){ return new Promise(function(resolve, reject){ function _animate(){ setTimeout(function(){ var marginLeft = parseInt(ball.style.marginLeft, 10) if(marginLeft === distance){ resolve() } else { if(marginLeft < distance){ marginLeft++ } else { marginLeft-- } ball.style.marginLeft = marginLeft + 'px' _animate() } },13); } _animate() }) } promiseAnimate(ball1, 100) .then(function() { return promiseAnimate(ball2,200) }).then(function(){ return promiseAnimate(ball3,300) }).then(function(){ return promiseAnimate(ball3,150) }).then(function(){ return promiseAnimate(ball2,150) }).then(function(){ return promiseAnimate(ball1,150) }) </script> </html>
var http = require('http') var Promise = require('bluebird') var cheerio = require('cheerio') //npm install cheerio var baseUrl = 'http://www.imooc.com/learn/' var url = 'http://www.imooc.com/learn/348' var videoIds = [728,637,197,348,259,75,134] function filterChapters(html){ var $ = cheerio.load(html) var chapters = $('.chapter') var title = $('h2.l').text() var number = $($('span.meta-value.js-learn-num')).text() // courseData = { // title: title, // number: number, // videos: [{ // chapterTitle: '', // videos: [ // title: '', // id: '' // ] // }] // } var courseData = { title: title, videos: [], number:number } chapters.each(function(item){ var chapter = $(this) var chapterTitle = chapter.find('strong').text().trim('\n').split('\n')[0] var videos = chapter.find('.video').children('li') var chapterData = { chapterTitle: chapterTitle, videos: [] } videos.each(function(item){ var video = $(this).find(".J-media-item") var videoTitle = video.text().split(/\s+/).slice(1,-2).join(' ') var id = video.attr('href').split('video/')[1] chapterData.videos.push({ title: videoTitle, id: id }) }) courseData.videos.push(chapterData) }) return courseData } function printCourseInfo(coursesData){ coursesData.forEach(function(courseData){ // console.log(courseData.number + ' 人學過' + courseData.title + '\n') console.log('### ' + courseData.title + '\n') courseData.videos.forEach(function(item){ console.log(item.chapterTitle); item.videos.forEach(function(video){ console.log(' [' + video.id + ']' + video.title + '\n') }) }) }) // coursesData.forEach(function(item){ // }) } function getPageAsync(url){ return new Promise(function(resolve,reject){ console.log('正在爬取 ' + url) http.get(url, function(res) { var html = '' res.on('data', function(data){ html += data }) res.on('end', function(){ resolve(html) // var courseData = filterChapters(html) // printCourseInfo(courseData) }) }).on('error', function(e){ reject(e) console.log('獲取課程數據錯誤') }) }) } var fetchCourseArray = [] videoIds.forEach(function(id){ fetchCourseArray.push(getPageAsync(baseUrl + id)) }) Promise .all(fetchCourseArray) .then(function(pages){ var coursesData = [] pages.forEach(function(html){ var courses = filterChapters(html) coursesData.push(courses) }) coursesData.sort(function(a,b){ return a.number < b.number }) printCourseInfo(coursesData) })
8. Buffer API
使用Buffer來讀寫圖片的一個例子:
1 var fs = require('fs') 2 3 fs.readFile('logo.png', function(err, origin_buffer){ 4 console.log(Buffer.isBuffer(origin_buffer)) 5 fs.writeFile('logo_buffer.png', origin_buffer, function(err){ 6 if(err) console.log(err) 7 }) 8 9 // var base64Image = new Buffer(origin_buffer).toString('base64') 10 var base64Image = origin_buffer.toString('base64') 11 12 console.log(base64Image) 13 14 var decodedImage = new Buffer(base64Image, 'base64') 15 16 console.log(Buffer.compare(origin_buffer, decodedImage)) 17 18 fs.writeFile('logo_decodes.png', decodedImage, function(err){ 19 if(err) console.log(err) 20 }) 21 })
9. Stream API
//拷貝文件 var fs = require('fs') var source = fs.readFileSync('../buffer/logo.png') fs.writeFileSync('stream_copy_logo.png', source)
//拷貝圖片 var fs = require('fs') var readStream = fs.createReadStream('stream_copy_logo.js') var n = 0 readStream .on('data', function(chunk) { n++ console.log('data emits') console.log(Buffer.isBuffer(chunk)) //true // console.log(chunk.toString('utf8')) //要讀的文件的內容 readStream.pause() console.log('data pause') setTimeout(function(){ console.log('data pause end') readStream.resume() }, 3000) }) .on('readable', function(){ console.log('data readable') }) .on('end', function() { console.log(n) console.log('data ends') }) .on('close', function() { console.log('data close') }) .on('error', function(e){ console.log('data read error' + e) })
//拷貝視頻 var fs = require('fs') var readStream = fs.createReadStream('1.mp4') var writeStream = fs.createWriteStream('1-stream.mp4') readStream.on('data', function(chunk){ //若是緩存區數據還在寫, 那麼暫停讀數據 if( writeStream.write(chunk) === false){ console.log('still cached') readStream.pause() } }) readStream.on('end', function(){ writeStream.end() }) writeStream.on('drain', function() { console.log('data drains') readStream.resume() })
10. 流與pipe
網絡請求與pipe:
1 var http = require('http') 2 var fs = require('fs') 3 var request = require('request') 4 5 http 6 .createServer(function(req, res) { 7 //=====================常規作法 8 // fs.readFile('./buffer/logo.png', function(err, data){ 9 // if(err){ 10 // res.end('file not exist!') 11 // } else { 12 // res.writeHeader(200, {'Context-Type' : 'text/html'}) 13 // res.end(data) 14 // } 15 // }) 16 17 //===============使用pipe方法讀取本地圖片 18 // fs.createReadStream('../buffer/logo.png').pipe(res) 19 20 //從網絡上獲取一張圖片 在不保存的前提下再返回給瀏覽器 21 request('http://www.imooc.com/static/img/index/logo.png?t=1.1').pipe(res) 22 //pipe會自動監聽data和end事件. 可自動控制流量壓力 23 }) 24 .listen(8090)
使用pipe重構上面的copy視頻的代碼:
1 var fs = require('fs') 2 fs.createReadStream('1.mp4').pipe(fs.createWriteStream('1-pipe.mp4'))
總結:
1 var Readable = require('stream').Readable 2 var Writable = require('stream').Writable 3 4 var readStream = new Readable() 5 var writeStream = new Writable() 6 7 readStream.push('I ') 8 readStream.push('Love ') 9 readStream.push('Imooc\n ') 10 readStream.push(null) 11 12 writeStream._write = function(chunk, encode, cb) { 13 console.log(chunk.toString()) 14 cb() 15 } 16 17 readStream.pipe(writeStream)
一個本身定製的讀寫轉換流的實現:
1 var stream = require('stream') 2 var util = require('util') 3 4 function ReadStream(){ 5 stream.Readable.call(this) 6 7 } 8 9 util.inherits(ReadStream, stream.Readable) 10 11 ReadStream.prototype._read = function(){ 12 this.push('I ') 13 this.push('Love ') 14 this.push('Imooc\n ') 15 this.push(null) 16 } 17 18 function WriteStream(){ 19 stream.Writable.call(this) 20 this._cached = new Buffer('') 21 } 22 23 util.inherits(WriteStream, stream.Writable) 24 25 WriteStream.prototype._write = function(chunk, encode, cb){ 26 console.log(chunk.toString()) 27 cb() 28 } 29 30 function TransformStream(){ 31 stream.Transform.call(this) 32 } 33 34 util.inherits(TransformStream, stream.Transform) 35 36 TransformStream.prototype._transform = function(chunk, encode, cb){ 37 this.push(chunk) 38 cb() 39 } 40 41 TransformStream.prototype._flush = function(cb){ 42 this.push('Oh Yeah!') 43 cb() 44 } 45 46 var rs = new ReadStream() 47 var ws = new WriteStream() 48 var ts = new TransformStream() 49 50 rs.pipe(ts).pipe(ws)