nodejs学习(imooc课程笔记, 主讲人Scott)
课程地址:
1. nodejs创建服务器
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安装:
一开始直接使用sudo apt-get install node后, 安装好的node不能启动且node -v也没有输出. node.js的版本号是v0.10.25.但是用npm安装一些包时候却说node版本不够, 没搞明白node和nodejs区别在哪里.
于是卸载掉从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
可以用了.
关于nodejs和node版本的区别,参考这个帖子吧: nodejs各版本的区别
3. 模块: 从这里开始都是慕课网老师Scott进击NodeJS基础(一)(二)课程的笔记
- 创建模块
teacher.js
- 导出模块
exports.add = function(){ } - 加载模块
var teacher = require('./teacher.js') - 使用模块
teacher.add('Scott')
4. nodejs中一些api
- url:
- url.parse

- url.format:

url.resolve

- url.parse
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>
- Promise就是对象,有三种状态: 未完成(pending), 已完成(fulfilled), 失败(rejected). 过程不可逆
- Promise A与A+不同点
- A+规范通过术语thenable来区分promise对象
- A+定义onFulfilled/onRejected必须是作为函数来调用, 而且调用过程必须是异步的
- A+严格定义了then方法链式调用时onFulfilled/onRejected的调用顺序
- 使用promise改进之前的爬虫代码:
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来读写图片的一个例子:
var fs = require('fs')
fs.readFile('logo.png', function(err, origin_buffer){
console.log(Buffer.isBuffer(origin_buffer))
fs.writeFile('logo_buffer.png', origin_buffer, function(err){
if(err) console.log(err)
})
// var base64Image = new Buffer(origin_buffer).toString('base64')
var base64Image = origin_buffer.toString('base64')
console.log(base64Image)
var decodedImage = new Buffer(base64Image, 'base64')
console.log(Buffer.compare(origin_buffer, decodedImage))
fs.writeFile('logo_decodes.png', decodedImage, function(err){
if(err) console.log(err)
})
})
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:
var http = require('http')
var fs = require('fs')
var request = require('request')
http
.createServer(function(req, res) {
//=====================常规做法
// fs.readFile('./buffer/logo.png', function(err, data){
// if(err){
// res.end('file not exist!')
// } else {
// res.writeHeader(200, {'Context-Type' : 'text/html'})
// res.end(data)
// }
// })
//===============使用pipe方法读取本地图片
// fs.createReadStream('../buffer/logo.png').pipe(res)
//从网络上获取一张图片 在不保存的前提下再返回给浏览器
request('http://www.imooc.com/static/img/index/logo.png?t=1.1').pipe(res)
//pipe会自动监听data和end事件. 可自动控制流量压力
})
.listen(8090)
使用pipe重构上面的copy视频的代码:
var fs = require('fs')
fs.createReadStream('1.mp4').pipe(fs.createWriteStream('1-pipe.mp4'))
总结:
- 可读流是为了读取外部数据, 并把数据缓存到内部的buffer数组
- 可写流是为了消费数据, 从可读流里获取数据然后对得到的chunk数据库进行处理.
var Readable = require('stream').Readable
var Writable = require('stream').Writable var readStream = new Readable()
var writeStream = new Writable() readStream.push('I ')
readStream.push('Love ')
readStream.push('Imooc\n ')
readStream.push(null) writeStream._write = function(chunk, encode, cb) {
console.log(chunk.toString())
cb()
} readStream.pipe(writeStream)
一个自己定制的读写转换流的实现:
var stream = require('stream')
var util = require('util')
function ReadStream(){
stream.Readable.call(this)
}
util.inherits(ReadStream, stream.Readable)
ReadStream.prototype._read = function(){
this.push('I ')
this.push('Love ')
this.push('Imooc\n ')
this.push(null)
}
function WriteStream(){
stream.Writable.call(this)
this._cached = new Buffer('')
}
util.inherits(WriteStream, stream.Writable)
WriteStream.prototype._write = function(chunk, encode, cb){
console.log(chunk.toString())
cb()
}
function TransformStream(){
stream.Transform.call(this)
}
util.inherits(TransformStream, stream.Transform)
TransformStream.prototype._transform = function(chunk, encode, cb){
this.push(chunk)
cb()
}
TransformStream.prototype._flush = function(cb){
this.push('Oh Yeah!')
cb()
}
var rs = new ReadStream()
var ws = new WriteStream()
var ts = new TransformStream()
rs.pipe(ts).pipe(ws)
nodejs学习(imooc课程笔记, 主讲人Scott)的更多相关文章
- Deeplearning.ai课程笔记--汇总
从接触机器学习就了解到Andrew Ng的机器学习课程,后来发现又出来深度学习课程,就开始在网易云课堂上学习deeplearning.ai的课程,Andrew 的课真是的把深入浅出.当然学习这些课程还 ...
- Nodejs学习笔记(三)——一张图看懂Nodejs建站
前言:一条线,竖着放,如果做不到精进至深,那就旋转90°,至少也图个幅度宽广. 通俗解释上面的胡言乱语:还没学会爬,就学起走了?! 继上篇<Nodejs学习笔记(二)——Eclipse中运行调试 ...
- Nodejs学习笔记(四)——支持Mongodb
前言:回顾前面零零碎碎写的三篇挂着Nodejs学习笔记的文章,着实有点名不副实,当然,这篇可能还是要继续走着离主线越走越远的路子,从简短的介绍什么是Nodejs,到如何寻找一个可以调试的Nodejs ...
- vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结
vue—你必须知道的 目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...
- Nodejs学习笔记(二)——Eclipse中运行调试Nodejs
前篇<Nodejs学习笔记(一)——初识Nodejs>主要介绍了在搭建node环境过程中遇到的小问题以及搭建Eclipse开发Node环境的前提步骤.本篇主要介绍如何在Eclipse中运行 ...
- NodeJS学习笔记之Connect中间件模块(一)
NodeJS学习笔记之Connect中间件模块(一) http://www.jb51.net/article/60430.htm NodeJS学习笔记之Connect中间件模块(二) http://w ...
- Nodejs学习笔记(六)--- Node.js + Express 构建网站预备知识
目录 前言 新建express项目并自定义路由规则 如何提取页面中的公共部分? 如何提交表单并接收参数? GET 方式 POST 方式 如何字符串加密? 如何使用session? 如何使用cookie ...
- Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例
目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...
- Nodejs学习笔记(十六)--- Pomelo介绍&入门
目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...
随机推荐
- 软件测试基础Ⅲ(osi7层协议,测试模型,LoadRunner组件,软件质量模型)
osi7层开放式系统互连网络模型 1.物理层:主要定义物理设备标准,如网线的接口类型.光纤的接口类型.各种传输介质的传输速率等.它的主要作用是传输比特流(就是由1.0转化为电流强弱来进行传输,到达目的 ...
- window下文件在Linux下文件乱码解决
在使用iconv转换文件的字符编码时,如果遇到类似“iconv: illegal input sequence at position”的错误,原因是需要转换的字符编码没有涵盖文件中的字符,比如,将一 ...
- 利用PHPExcel读取excel文件
$filePath = "7788.xls"; $PHPExcel = new PHPExcel(); $PHPReader = new PHPExcel_Reader_Excel ...
- 【转载】 了解实时媒体的播放(RTP/RTCP 和 RTSP)
http://blog.csdn.net/span76/article/details/12913307 离线媒体只是用 Http协议去读取服务器端文件而已,而对于实时直播如何实现, 这里就要用到 R ...
- yum安装nginx 加载image_filter 加载方式
通过yum安装的nginx 加载image_filter方式方法: yum install -y gd-devel libgd gcc libgdyum install -y nginx-module ...
- css扩大超链接的点击范围
给a标签设置display:block后,它会根据盒模型计算a标签的实际大小.这时候,你可以使用hover伪类使a的整个盒模型生效..link a{display:block;padding:2px ...
- linux cp操作,每天学习一点
指令名称:cp(copy)功能介绍:将一个文件复制至另一个文件,或将数个文件复制至另一目录. 语法格式: cp [options] source dest cp [options] source.. ...
- VSCode的终端修改
快速打开VSCode的快捷键是:Ctrl + `(反引号) 转自:https://blog.csdn.net/u013517122/article/details/82776607 因本人实在忍受不了 ...
- 关于css中设置属性的常识
1.cellspacing 属性规定单元格之间的空间,请勿将该属性与 cellpadding 属性相混淆. 2.cellpadding 属性规定的是单元边沿与单元内容之间的空间. 3.text-ali ...
- Jersey RESTful WebService框架学习(二)使用@PathParam
@PathParamuri路径参数写在方法的参数中,获得请求路径参数.比如:@PathParam("username") String userName 前端请求: <!DO ...