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 ...
随机推荐
- window下文件在Linux下文件乱码解决
在使用iconv转换文件的字符编码时,如果遇到类似“iconv: illegal input sequence at position”的错误,原因是需要转换的字符编码没有涵盖文件中的字符,比如,将一 ...
- mybatis学习 十六 auto_mapping实现连表查询
只能使用多表联合查询方式. 要求:查询出的列别和属性名相同. 点字符 "." 在 SQL 是关键字符,两侧添加反单引号(Tab键上的一个字符) <select id=&q ...
- js中实现 复制到剪切板 功能
一:引包 <script type="text/javascript" src="jquery.js"></script> <sc ...
- 回文日期(NOIP2016)
题目:回文日期 这题虽然说不难,但是也不能算水了. 我先讲讲思路.60分的算法很好写,就是判断一下是不是回文串,分离每个数位,判断即可. 但我们的目标是满分,所以我来讲讲满分算法. 首先,给的是区间, ...
- 进度条的制作unity
不说了直接上代码: LoadingPanel: using UnityEngine;using System.Collections;using UnityEngine.UI;using UnityE ...
- MZOJ 1344 工作依赖
这道题并不是很难,关键在于读入; 其余只需一个遍历;(考的时候傻逼兮兮的没写出来) 另外,学到了一个 isdigit()用来判断是否是0-9的数字; #include <bits/stdc++. ...
- 核心一:DI
1.DI:中文名称:依赖注入 2.英文名称:(Dependency Injection) 3.DI是什么?? 3.1 DI和IoC是一样的 3.2 当一个类(A)中需要依赖另一类(B)对象时,把B赋值 ...
- 2019.01.26 codeforces 632E. Thief in a Shop(生成函数)
传送门 题意简述:给nnn个物件,物件iii有一个权值aia_iai,可以选任意多个.现在要求选出kkk个物件出来(允许重复)问最后得到的权值和的种类数. n,k,ai≤1000n,k,a_i\le ...
- [小结]了解innodb锁
原创文章,会不定时更新,转发请标明出处:http://www.cnblogs.com/janehoo/p/5603983.html 背景介绍: innodb的锁分两类:lock和latch. 其中la ...
- c语言结构体链表
原文链接:http://zhina123.blog.163.com/blog/static/417895782012106036289/ 引用自身的结构体,一个结构体中有一个或多个成员的基类型就是本结 ...