一.NodeJS基本介绍
1.Node-Webkit、appjs:允许开发者使用Web技术,html/css来开发跨平台的桌面应用程序,能兼容mac、Linux、Windows
2.Jade:和NodeJS组合使用,可以高效的管理后台html模板
3.Ghost:是一个强大且体验超好的开源博客程序
4.Grunt:是javascript跑各种任务的运行工具,通过集成各种插件来完成比如样式编译、脚本检查、脚本压缩合并、自动化测试、Shell脚本运行、文档生成,甚至是图片处理等等各种各样的任务。
5.gulp:针对grunt的复杂配置有了更简洁高效的组织方式
6.Express.js:基于Node.js 平台,快速、开放、极简的 web 开发框架
7.Nodecast:先是在PC端运行它,然后启动移动设备,选择一个支持Nodecast的应用程序,然后就可以把移动广播中的内容映射到电脑上,等于把电脑当一个流媒体来使用
8.Log.io:让你在浏览器里面可以实时地监控项目日志
9.PDFKit:用来生成PDF文档
10.Haroopad:是一个Linux上的markdown编辑器
11.NoduinoWeb:硬件黑客希望通过Noduino Web页面来控制开源硬件,从而将软件和硬件很好的结合起来
12.NodeOS:是一款基于Node.js的开发的友好的操作系统
二.学习NodeJS推荐四个网站
1.nodejs.org,官网
2.www.npmjs.com,模块社区搜索对应的模块,参加别人代码是如何组织的
3.github.com,阅读优秀的源码
4.stackoverflow.com,技术问答社区
三.Node.js的版本
偶数位为稳定的版本 -0.6.x,-0.8.x,-0.10.x
奇数位为非稳定的版本 -0.7.x,-0.9.x,-0.11.x
四.Windows上安装git bash
一路下一步安装完毕
五.安装nodejs
https://nodejs.org/下载nodejs安装成功后,会自动在环境变量的Path中添加nodejs的安装路径
运行环境:如下是在Chrome浏览器上运行js和在Node.js中运行js
第一个实例:server.js
const http = require('http'); const hostname = '127.0.0.1'; const port = 3000; const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello Node.js\n'); }); server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
在git bash上进入server.js所在的目录,输入node server.js
然后在浏览器中输入:http://127.0.0.1:3000/,运行效果如下:
六.模块与包管理工具
实例:
teacher.js
function add(teacher) { console.log('Add Teacher:' + teacher) } exports.add = add
student.js
function add(student) { console.log('Add Student:' + student) } exports.add = add
klass.js
var student = require('./student.js') var teacher = require('./teacher.js') function add(teacherName, students) { teacher.add(teacherName) students.forEach(function(item, index) { student.add(item) }) } //传统的模块实例,exports是module的一个辅助方法,推荐这种方式 exports.add = add //实例成为特殊的模块类型,真实存在的东西,返回调用者exports挂载的属性和方法赋给module.exports //如果module.exports存在属性和方法,则被忽略 //module.exports = add
index.js
var klass = require('./klass') klass.add('Scott', ['白富美','高富帅']) exports.add = function(klasses) { klasses.forEach(function(item, index) { var _klass = item var teacherName = item.teacherName var students = item.students klass.add(teacherName, students) }) }
七.Node.js API
分化为node.js、io.js两个阵营
八.URL网址解析的好帮手
url.parse('http://imooc.com/course/list') Url { protocol: 'http:', slashes: true, auth: null, host: 'imooc.com', port: null, hostname: 'imooc.com', hash: null, search: null, query: null, pathname: '/course/list', path: '/course/list', href: 'http://imooc.com/course/list' } > url.parse('http://imooc.com:8080/course/list?from=scott&course=node#floor!') Url { protocol: 'http:', slashes: true, auth: null, host: 'imooc.com:8080', port: '8080', hostname: 'imooc.com', hash: '#floor!', search: '?from=scott&course=node', query: 'from=scott&course=node', pathname: '/course/list', path: '/course/list?from=scott&course=node', href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor!' } > url.format({ ... protocol: 'http:', ... slashes: true, ... auth: null, ... host: 'imooc.com:8080', ... port: '8080', ... hostname: 'imooc.com', ... hash: '#floor!', ... search: '?from=scott&course=node', ... query: 'from=scott&course=node', ... pathname: '/course/list', ... path: '/course/list?from=scott&course=node', ... href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor!' } ... ) 'http://imooc.com:8080/course/list?from=scott&course=node#floor!' > url.resolve('http://imooc.com/','/course/list') 'http://imooc.com/course/list' > url.parse('http://imooc.com:8080/course/list?from=scott&course=node#floor1') Url { protocol: 'http:', slashes: true, auth: null, host: 'imooc.com:8080', port: '8080', hostname: 'imooc.com', hash: '#floor1', search: '?from=scott&course=node', query: 'from=scott&course=node', pathname: '/course/list', path: '/course/list?from=scott&course=node', href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor1' } > url.parse('http://imooc.com:8080/course/list?from=scott&course=node#floor1', t rue) Url { protocol: 'http:', slashes: true, auth: null, host: 'imooc.com:8080', port: '8080', hostname: 'imooc.com', hash: '#floor1', search: '?from=scott&course=node', query: { from: 'scott', course: 'node' }, pathname: '/course/list', path: '/course/list?from=scott&course=node', href: 'http://imooc.com:8080/course/list?from=scott&course=node#floor1' } > url.parse('//imooc.com/course/list',true) Url { protocol: null, slashes: null, auth: null, host: null, port: null, hostname: null, hash: null, search: null, query: {}, pathname: '//imooc.com/course/list', path: '//imooc.com/course/list', href: '//imooc.com/course/list' } > url.parse('//imooc.com/course/list',true,true) Url { protocol: null, slashes: true, auth: null, host: 'imooc.com', port: null, hostname: 'imooc.com', hash: null, search: null, query: {}, pathname: '/course/list', path: '/course/list', href: '//imooc.com/course/list' } >
九.QueryString参数处理小利器
> querystring.stringify({name:'scott', course:['jade','node'], from:''}) 'name=scott&course=jade&course=node&from=' > querystring.stringify({name:'scott', course:['jade','node'], from:''}, ',') 'name=scott,course=jade,course=node,from=' > querystring.stringify({name:'scott', course:['jade','node'], from:''}, ',', ':') 'name:scott,course:jade,course:node,from:' > querystring.parse('name=scott&course=jade&course=node&from=') { name: 'scott', course: [ 'jade', 'node' ], from: '' } > querystring.parse('name=scott,course=jade,course=node,from=', ',') { name: 'scott', course: [ 'jade', 'node' ], from: '' } > querystring.parse('name=scott,course=jade,course=node,from=') { name: 'scott,course=jade,course=node,from=' } > querystring.parse('name=scott,course=jade,course=node,from=', ',', '=') { name: 'scott', course: [ 'jade', 'node' ], from: '' } > querystring.escape('<哈哈>') '%3C%E5%93%88%E5%93%88%3E' > querystring.unescape('%3C%E5%93%88%E5%93%88%3E') '<哈哈>'
十.HTTP知识先填坑
http客户端发起请求,创建端口
http服务器在端口监听客户端请求
http服务器向客户端返回状态和内容
当输入网址回车,页面就出来了,但计算机和浏览器做了许许多多的事情:
1.Chrome搜索自身的DNS缓存
浏览器上输入:chrome://net-internals/#dns,就可以查看曾经浏览过的网站的DNS缓存记录
2.搜索操作系统自身的DNS缓存(浏览器没有找到缓存或缓存已经失效)
如浏览器没有找到缓存或已失效,则搜索操作系统自身的DNS缓存,如找到且没有过期,则会停止搜索,解析到此结束
3.读取本地的HOST文件
十一.HTTP事件回调进阶
HTTP模块有考虑支持很多HTTP协议的特性,这些特性在传统开发中确很难使用,比如大体积的扩编码的消息,除此之外,为了让用户可以在请求和响应中使用流的形式操作数据,
接口从不缓存整个请求或者响应,整个HTTP API都很底层,它只处理流相关的操作以及信息解析,可以把信息解析成请求头、请求体,但并不去解析实际的请求头和请求正文里面的具体内容。
1.HTTP概念进阶
a.什么是回调?
异步编程最基本的方法,需按顺序执行异步逻辑时,一般采用后续传递的方法。也就是将后续逻辑封装在回调函数中做为起始函数的参数层层嵌套,通过这种方式来让程序按照我们所期望的方式走完整个流程。
callback.js
function learn(something) { console.log(something) } function we(callback, something) { something += ' is cool' callback(something) } we(learn, 'Nodejs') we(function(something) { console.log(something) }, 'Jade')
b.什么是同步/异步?
同步就是执行一个任务,后面一个任务等待前一个任务结束。
每个任务有一个或多个回调函数
async.js
var c = 0 function printIt() { console.log(c) } function plus() { setTimeout(function() { c += 1 }, 1000) } plus() printIt()
async2.js
var c = 0 function printIt() { console.log(c) } function plus(callback) { setTimeout(function() { c += 1 callback() }, 1000) } plus(printIt)
c.什么是I/O?
磁盘的写入和读出,为文件系统、数据库资料提供接口,向文件系统发送请求时,不用等到硬盘,硬盘准备好了,非阻塞接口会通知到Node
d.什么是单线程/多线程?
单线程代码是按顺序执行的,多线程代码
e.什么是阻塞/非阻塞
f.什么是事件?
鼠标点击、拖拽窗口都是事件
g.什么是事件驱动?
function clickIt(e) { window.alert('Button is cliecked') } var button = document.getElementById('#button') button.addEventListener('click', clickIt)
这几行代码就能实现当按钮被点击时就能触发一个回调函数,就是这个clickIt,弹出一个框
所有能触发事件的对象,都是Event下面的EventEmitter的实例
为了某个事件注册函数,像这个函数不是马上执行,只有当事件发生时才会调用回调函数,这种函数执行的方式就叫做事件驱动。
h.什么是基于事件驱动的回调?
这种注册回调就是基于事件驱动的回调,如果这些回调和异步IO操作有关,则就可以看作是基于回调的异步IO,只不过这种回调是在Node.js里面是由事件来驱动的。
i.什么是事件循环?
如果有大量的异步操作,以及IO的耗时操作,甚至是一些定时器控制的延时操作,它们完成时都要去调用相应的回调函数,从而来完成一些密集的任务,而又不会阻塞整个程序执行的流程,那这个时候,这么多事件就需要一个机制来管理,这种机制就是事件循环。
EventLoop是一个回调函数队列,当异步函数执行的时候,回调函数就会被压入到这人队列,对Node.js来说,靠一个单线程不断地查询队列中是否有事件,当它读取到一个事件时,将调用与这个事件关联的javaScript函数。
事件循环是一个先进先出的任务队列,回调就按照它们被加入的顺序来执行。整个队列可以理解成普通函数和回调函数构成的一个完整的队列。
十二.HTTP源码解读
1.什么是作用域?
作用域和调用函数访问变量的能力有关
分:局部作用域和全局作用域
2.什么是上下文?
this关键字有关,是调当前可执行代码的引用
在js里面,this关键字通常是指向当前函数的拥有者,通常把拥有者叫做执行上下文。
this是JS语言的一个关键字,代表函数运行时自动生成的一个内部对象,只能在函数内部使用。
同时,对于函数的上下文执行对象,需要依据当前的运行环境而定,因为上下文执行对象在程序运行时来确定,也可以动态去改变。
在全局运行的上下文中,this指向的是全局对象,在函数内部,this取决于函数被调用的方式,被调用的方式主要有:
a.作为对象的方法,pet.speak(),里面的this指向的对象就是pet这个对象
b.直接函数调用,这时内部的this指向的是全局对象
c.在构造函数中使用this,那这个this就指向到新构建好的对象,就是实例对象。
JS的上下文存在一个定义时的上下文和运行时的上下文以及上下文可以改变的。
使用call和apply可以改变上下文执行对象,可以让你在自定义上下文中执行函数,作用一样,用法有区别。call函数需要一个参数列表,apply允许传递一个参数做为数组。作用是调用一个对象的方法,利用另一个对象替换当前对象,其实就是更改对象this指向的内容。说的标准点就是,以某个方法当做指定的某个对象的方法来执行。
3.HTTP源码解读
十三.HTTP性能小测试
1.Apache ab
在命行里输入:ab -n1000 -c10 http://localhost:3000/
-n1000:总的请求数是1000,默认是1
-c10:并发数是10,默认是1
-t:用来测试进行的总时间
-p:post时的数据文件
-w:以html表格格式输出结果
2.ab -n1000 -c10 http://www.imooc.com/
慕课网性能小测试
十四.HTTP爬虫
借助HTTP API,使用cheerio抓取网页数据,npm install cheerio
十五.事件模块小插曲
event emit可以为某个事件添加最多10个监听函数。
官方建议对一个事件不要设置超过10个监听器,太多会导致内存泄露。
十六.Node.js request方法
HTTP get/request
get是对request一个封装,get能做的事,request都能做。
http.request(options[,callback])
host,path,hostname,headers,port,auth,localAddress,agent,socketPath,keepAlive,method,keepAliveMsecs
学习视频《进击Node.js基础(一)》