课程地址:

进击Node.js基础(一)

进击Node.js基础(二)

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

  1. url:
    1. url.parse
    2. url.format:
    3. url.resolve

  2. querystring

  

5. 用nodejs做的一个爬虫:

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'))

总结:

  1. 可读流是为了读取外部数据, 并把数据缓存到内部的buffer数组
  2. 可写流是为了消费数据, 从可读流里获取数据然后对得到的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)的更多相关文章

  1. Deeplearning.ai课程笔记--汇总

    从接触机器学习就了解到Andrew Ng的机器学习课程,后来发现又出来深度学习课程,就开始在网易云课堂上学习deeplearning.ai的课程,Andrew 的课真是的把深入浅出.当然学习这些课程还 ...

  2. Nodejs学习笔记(三)——一张图看懂Nodejs建站

    前言:一条线,竖着放,如果做不到精进至深,那就旋转90°,至少也图个幅度宽广. 通俗解释上面的胡言乱语:还没学会爬,就学起走了?! 继上篇<Nodejs学习笔记(二)——Eclipse中运行调试 ...

  3. Nodejs学习笔记(四)——支持Mongodb

    前言:回顾前面零零碎碎写的三篇挂着Nodejs学习笔记的文章,着实有点名不副实,当然,这篇可能还是要继续走着离主线越走越远的路子,从简短的介绍什么是Nodejs,到如何寻找一个可以调试的Nodejs ...

  4. vue—你必须知道的 js数据类型 前端学习 CSS 居中 事件委托和this 让js调试更简单—console AMD && CMD 模式识别课程笔记(一) web攻击 web安全之XSS JSONP && CORS css 定位 react小结

    vue—你必须知道的   目录 更多总结 猛戳这里 属性与方法 语法 计算属性 特殊属性 vue 样式绑定 vue事件处理器 表单控件绑定 父子组件通信 过渡效果 vue经验总结 javascript ...

  5. Nodejs学习笔记(二)——Eclipse中运行调试Nodejs

    前篇<Nodejs学习笔记(一)——初识Nodejs>主要介绍了在搭建node环境过程中遇到的小问题以及搭建Eclipse开发Node环境的前提步骤.本篇主要介绍如何在Eclipse中运行 ...

  6. NodeJS学习笔记之Connect中间件模块(一)

    NodeJS学习笔记之Connect中间件模块(一) http://www.jb51.net/article/60430.htm NodeJS学习笔记之Connect中间件模块(二) http://w ...

  7. Nodejs学习笔记(六)--- Node.js + Express 构建网站预备知识

    目录 前言 新建express项目并自定义路由规则 如何提取页面中的公共部分? 如何提交表单并接收参数? GET 方式 POST 方式 如何字符串加密? 如何使用session? 如何使用cookie ...

  8. Nodejs学习笔记(十五)--- Node.js + Koa2 构建网站简单示例

    目录 前言 搭建项目及其它准备工作 创建数据库 创建Koa2项目 安装项目其它需要包 清除冗余文件并重新规划项目目录 配置文件 规划示例路由,并新建相关文件 实现数据访问和业务逻辑相关方法 编写mys ...

  9. Nodejs学习笔记(十六)--- Pomelo介绍&入门

    目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...

随机推荐

  1. window下文件在Linux下文件乱码解决

    在使用iconv转换文件的字符编码时,如果遇到类似“iconv: illegal input sequence at position”的错误,原因是需要转换的字符编码没有涵盖文件中的字符,比如,将一 ...

  2. mybatis学习 十六 auto_mapping实现连表查询

    只能使用多表联合查询方式. 要求:查询出的列别和属性名相同. 点字符  "."  在 SQL 是关键字符,两侧添加反单引号(Tab键上的一个字符) <select id=&q ...

  3. js中实现 复制到剪切板 功能

    一:引包 <script type="text/javascript" src="jquery.js"></script> <sc ...

  4. 回文日期(NOIP2016)

    题目:回文日期 这题虽然说不难,但是也不能算水了. 我先讲讲思路.60分的算法很好写,就是判断一下是不是回文串,分离每个数位,判断即可. 但我们的目标是满分,所以我来讲讲满分算法. 首先,给的是区间, ...

  5. 进度条的制作unity

    不说了直接上代码: LoadingPanel: using UnityEngine;using System.Collections;using UnityEngine.UI;using UnityE ...

  6. MZOJ 1344 工作依赖

    这道题并不是很难,关键在于读入; 其余只需一个遍历;(考的时候傻逼兮兮的没写出来) 另外,学到了一个 isdigit()用来判断是否是0-9的数字; #include <bits/stdc++. ...

  7. 核心一:DI

    1.DI:中文名称:依赖注入 2.英文名称:(Dependency Injection) 3.DI是什么?? 3.1 DI和IoC是一样的 3.2 当一个类(A)中需要依赖另一类(B)对象时,把B赋值 ...

  8. 2019.01.26 codeforces 632E. Thief in a Shop(生成函数)

    传送门 题意简述:给nnn个物件,物件iii有一个权值aia_iai​,可以选任意多个.现在要求选出kkk个物件出来(允许重复)问最后得到的权值和的种类数. n,k,ai≤1000n,k,a_i\le ...

  9. [小结]了解innodb锁

    原创文章,会不定时更新,转发请标明出处:http://www.cnblogs.com/janehoo/p/5603983.html 背景介绍: innodb的锁分两类:lock和latch. 其中la ...

  10. c语言结构体链表

    原文链接:http://zhina123.blog.163.com/blog/static/417895782012106036289/ 引用自身的结构体,一个结构体中有一个或多个成员的基类型就是本结 ...