Node.js基础
先阅读菜鸟教程:
JavaScript: https://www.runoob.com/js/js-tutorial.html
TypeScript: https://www.runoob.com/typescript/ts-tutorial.html
Node.js: https://www.runoob.com/nodejs/nodejs-tutorial.html
Node.js 安装配置、NPM 使用介绍、Node.js REPL、
Node.js 回调函数、Node.js 事件循环、Node.js EventEmitter、Node.js Buffer、Node.js Stream、
Node.js 模块系统、Node.js 函数、Node.js 路由、Node.js 全局对象、Node.js 常用工具、Node.js 文件系统、
Node.js GET/POST请求、Node.js 工具模块、Node.js Web 模块、Node.js Express 框架、Node.js RESTful API、
Node.js 多进程、Node.js JXcore 打包、Node.js MySQL、Node.js MongoDB
学习资源
官方API文档 https://nodejs.org
《深入浅出Node.j s》 偏理论、《Node.js权威指南》API讲解,偏理论
阮一峰博客:http://www.ruanyifeng.com/blog/javascript/
Node.js入门 https://www.nodebeginner.org/index-zh-cn.html
cnode社区 https://cnodejs.org/
B站资源:
https://www.bilibili.com/video/BV1Ns411N7HU?p=120
https://www.bilibili.com/video/BV11t411k79h?p=40
知识点
模块系统
使用Node编写应用程序主要在使用:
1)EcmaScript语言
2)核心模块:fs、http、os等
3)第三方模块:通过npm下载
4)自定义模块
在node中没有全局作用域的概念(有全局对象global作为全局变量的宿主);
在node中,只能通过require方法来加载执行多个JavaScript脚本文件;
模块是完全封闭的,外部无法访问内部,内部也无法访问外部;
每个模块中都提供一个对象module对象,该module对象中,有一个成员 exports也是一个对象,谁来require这个模块,谁就可以得到模块内部的module.exports对象,默认在代码的最后有一句return module.exports;
为了简化使用node用exports来等价于使用module.exports, 是其的引用,return的还是module.exports;exports默认是一个空对象,可以把需要被外部访问的成员挂载到exports接口对象中;
如果要对外暴露属性或方法,就用 exports 就行,要暴露对象(类似class,包含了很多属性和方法),就用 module.exports;
核心模块
官方文档详细说明:https://nodejs.org/dist/latest-v12.x/docs/api/,
例如File System: https://nodejs.org/docs/latest-v13.x/api/fs.html , 顶部是文档索引、然后是具体的使用说明
模块查找机制
优先从缓存加载
核心模块
路径形式的文件模块
第三方模块
第三方模块如何加载的
第三方包和核心模块的名字是不可能相同的,如果加载时既不是核心模块也不是路径形式的模块,则:
先找当前文件所处目录中的node_modules目录,如模块名是art-template
node_modules/art-template
node_modules/art-template/package.json文件
node_modules/art-template/package.json文件 中的 main 属性,记录了art-template的入口模块
然后加载这使用这个第三方包,实际上最终加载的还是文件
如果package.json不存在或main指定的入口模块没有,则node会自动加载该目录下的index.js
如果以上所有条件都不成立,则会进入上一级目录中的node_modules目录查找,直到到磁盘根目录,
还找不到会报错 can not find moulde ...
注意:不会去兄弟目录里查找,只会在当前和父级目录里去找
require
require方法有两个作用:
1)加载文件模块并执行里面的代码
2)拿到被加载文件模块导出的接口对象
ip定位网络中计算机、端口定位服务(应用程序)
响应内容类型Content-type
服务器默认发送数据是utf8编码,浏览器在不知道服务器响应内容编码时会按当前操作系统的默认编码去解析,中文操作系统默认是gbk,所以需要告诉浏览器服务返回编码 res.setHeader('Content-Type', 'text/plain; charset=utf-8'); text/plain 普通文本,text/html html文本
Http Mime-type列表: https://tool.oschina.net
node中用art-template或ejs模版引擎
npm
1)npm网站: https://www.npmjs.com ,供搜索第三方包或者发自己的包
2)npm 命令行工具,只要你安装了node就已经安装了npm
版本 npm --version
升级 npm install --global npm
3)常用命令:
npm init
// npm init -yes 快速生成
npm install
// 一次性把dependencies选项中的依赖全部安装
// 简写 npm i
npm install 包名
// 简写 npm i 包名
npm install --save 包名 // 下载并保存依赖项(package.json文件中的dependencies选项)
// 简写 npm i -S 包名
npm uninstall 包名 // 只删除,如果有依赖会依然保存
// 简写 npm un 包名
npm uninstall --save 包名 // 删除的同时也会把依赖信息去掉
// 简写 npm un -S 包名
npm install jquery@1.8.0
// 用 @ 指定版本安装
npm list 查看当前目录下已安装哪些包,包括依赖包
npm info 包名,查看包信息
// 如 npm jquery
npm help // 查看使用帮助
npm 命令 --help // 查看指定命令的使用帮助
4)解决npm被墙问题
http://npm.taobao.org 安装淘宝的cnpm, 命运用cnpm代替npm
用supervisor代替node命令启动应用
npm install -g supervisor
// 然后 node s.js 可用为 supervisor s.js
package.json
dependencies: 配置当前程序依赖的其他包
devDependencies: 配置当前程序所依赖的其他包,比如一些工具之类的配置在这里
"dependencies": {
"ejs": "^2.3.4",
"express": "~4.13.3",
"egg": "*1.0.17",
}
// 前面不带符号的表示固定版本;
// ~ 表示前两位不变,最后一个取最新的;
// ^ 表示第一位版本号不变,后面两位取最新的;
// * 表示全部取最新的;
exptress框架
TJ Holowaychuk https://github.com/tj
find与findIndex原理
var users = [
{id: 1, name: '张一'},
{id: 2, name: '张二'},
{id: 3, name: '张三'},
]
Array.prototype.myFind = function (conditionFunc) {
for (var i = 0; i < this.length; i++) {
if (conditionFunc(this[i], i)) {
return this[i]
}
}
}
var ret = users.myFind(function (item, index) {
return item.id = 2
})
console.log(ret)
js中的call方法和apply方法
https://www.cnblogs.com/zwjx/p/9686228.html
Es6常见语法:1.let const 2.模版字符串 3.属性、对象的简写 4.箭头函数 5.Promise
let与const
https://www.runoob.com/js/js-let-const.html
反引号来定义多行文本或内嵌表达式
var name = '张三';
var age = 20;
console.log(`${name}的年龄是${age}`);
对象、属性的简写
var name = 'zhangsan';
var app = {
name: name,
run: function() {
console.log('run');
}
};
// 属性名与变量名一样时,属性简写:
// 方法的简写:
var app = {
name,
run() {
}
};
箭头函数
https://www.jianshu.com/p/73cbeb6782a0
Promise
https://www.jianshu.com/p/d963e90af588
then里第一个函数就是前面成功执行后执行的函数,参数data就是成功执行的结果,这个为读取的文件内容。
当p1读取成功,当前函数return的结果可以在后面then中function接收到;
当return一个Promise的时候,可以实现异步方法的链式调用。return了Promise才能继续then捏
jQuery对Promise支持, 自己封装一个比如ajax的get
Async、Await和Promise使用
一、async和await是什么
ES2017 标准引入了 async 函数,使得异步操作变得更加方便,async其实本质是Generator函数的语法糖
async表示函数里有异步操作
await表示在后面的表达式需要等待结果
async函数返回的是一个Promise对象,可以使用then方法添加回调函数,一旦遇到await就会先返回。
二、node异步编程演进的四个阶段
我们来回顾一下异步编程的写法的演进过程
第1阶段 通过回调函数
fs.readFile('/etc/passwd', 'utf-8', function (err, data) {
if (err) throw err;
console.log(data);
})
这样的方式会造成嵌套过多,在调用过多的时候,就变成了下面这样的写法,传说中的callback hell
fs.readFile(fileA, 'utf-8', function (err, data) {
fs.readFile(fileB, 'utf-8', function (err, data) {
fs.readFile(fileC, 'utf-8', function (err, data) {
// ...
});
});
});
第2阶段 通过Promise
Promise 对象允许将回调函数的嵌套,改成链式调用。
采用 Promise,连续读取多个文件,写法如下。
const readFile = function (fileName) {
return new Promise(function (resolve, reject) {
fs.readFile(fileName, function(error, data) {
if (error) return reject(error);
resolve(data);
});
});
};
当操作很多的时候就变成了下面这样的写法
var readFile = require('fs-readfile-promise');
readFile(fileA)
.then(function (data) {
console.log(data.toString());
})
.then(function () {
return readFile(fileB);
})
.then(function (data) {
console.log(data.toString());
})
.catch(function (err) {
console.log(err);
});
这样虽然比callback好了,但是有一个问题是代码冗余,不管什么操作,看上去都是一堆then
第3阶段 通过Generator函数
function* asyncJob() {
// ...其他代码
var f = yield readFile(fileA);
// ...其他代码
}
函数asyncJob是一个协程,协程遇到yield命令就暂停,等到执行权返回,再从暂停的地方继续往后执行,这样的写法非常像同步操作。
要想使用yield方法,得不停地执行next()切换到下一个yeild,调用变成了下面这样
var fs = require('fs');
var readFile = function (fileName){
return new Promise(function (resolve, reject){
fs.readFile(fileName, function(error, data){
if (error) return reject(error);
resolve(data);
});
});
};
var gen = function* (){
var f1 = yield readFile('/etc/fstab');
var f2 = yield readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
第4阶段 通过async和await
async 函数本质就是 Generator 函数的语法糖
最后演变成了下面这样的写法
const asyncReadFile = async function () {
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
async和await,比起*和yield,语义更清楚了。
async表示函数里有异步操作,await表示在后面的表达式需要等待结果
async函数的返回值是Promise对象
await后面,可以是Promise对象和原始类型的值(数值、字符串和布尔值,会自动转换成resolved的Promise对象)