这是本文档旧的修订版!
NodeJS/Javascript
News:
- Nodejs v4.0.0 之后的版本需要 gcc 4.7版本以上来进行 addon 编译. GCC 4.7 or newer is required due to V8 using the template alias feature in C++.
1. V8 GC
2. ECMAScript
- 目前各大浏览器的JS实现符合ES5.1版;ES6的实现情况
- nodejs 0.11.* 实现部分es6特性, 要使用需要加上
–harmnoy
3. Packages
- awesome-nodejs 这里可以分类查找你想要的库!
Modules
- commonjs Modules/1.0
- modules doc modules cycles 注意关于模块互相包含的处理机制
npm or yarn
- npm 使用国内淘宝源
npm config set registry https://registry.npm.taobao.org # 配置后可通过下面方式来验证是否成功 npm config get registry npm get registry npm info webpack # 恢复 npm config rm registry
- yarn: 更快更安全
pm2
- pm2 nodejs进程管理工具, 可
- 进程运行状态监测,进程重启
- 管理进程集群
- 超过指定内存则重启
- 文件改动则重启
async
promise
- Callbacks are imperative (async)回调风格是显式的控制处理流程来把很多值组织在一起,而 promises 是显式表达出值的关系来把控制流的各个组件连接在一起。回调是指令式的,promises 是函数式的
- 引自这篇文章:如果有异常没有捕捉到怎么样?如果有一个异常一直被传递到最顶层调用栈还没有被捕捉,那么就会导致进程的崩溃退出,不过我们还有两个终极捕捉手段:
process.on('uncaughtException', (err) => { console.error(err); });
uncaughtException
事件可以捕捉到那些已经被抛出到最顶层调用栈的异常,一旦添加了这个监听器,这些异常便不再会导致进程退出。实际上有一些比较激进的人士认为程序一旦出现事先没有预料到的错误,就应该立刻崩溃,以免造成进一步的不可控状态,也为了提起开发人员足够的重视。但我从比较务实的角度建议还是不要这样做,尤其是服务器端程序,一个进程崩溃重启可能需要一分钟左右的时间,这段时间会造成服务的处理能力下降,也会造成一部分连接没有被正确地处理完成,这个后果很可能是更加严重的。但我们应当将在这个事件中捕捉到的错误视作非常严重的错误,因为在此时已经丢失了和这个错误有关的全部上下文,必然无法妥善地处理这个错误,唯一能做的就是打印一条日志。process.on('unhandledRejection', (reason, p) => { console.error(reason, p); });
unhandledRejection
事件可以捕捉到那些被 reject 但没有被添加 .catch 回调的 Promise, 通常是因为你忘记为一个返回 Promise 的函数添加 return。因为 Promise 本来就是对异步错误的一种封装,所以实际使用中偶尔也会出现 Promise 先被 reject, 而后再用 .catch 添加错误处理的情况,所以这个事件实际上偶尔会有误报。
- 对数组或对象或map进行顺序的异步任务时,可以这样
//要得到一个then then then的promise链,先定义一个已经resolve了的promise,然后依次往后then… var sequence = Promise.resolve(); array.forEach(function(item) { sequence = sequence.then(...) });
express
- 4.0 开始 express 废弃 connect, 默认的文件上传插件
multer
需要手动引入
3.7 winston
- Console 默认不以json格式记录, File默认以json格式记录, 可以用
json:true/false
来修改 prettyPrint
会把object或json展开成多行, 利于肉眼观察不利于grep分析
moment
- 坑!moment如果使用object构造, 其中参数月份的值范围是0~11, 而其它构造方式是1~12;
- 改用 day.js
http-server
- 使用方便的静态http服务
sudo npm i http-server -g
安装, 之后使用http-server
命令来启动静态网站.
一些好用的库
tips
- node-gyp 提示错误
/home/you/.node-gyp/0.10.26/common.gypi not found
,原因可能是上一次失败引起,直接删除.node-gyp
整个文件夹迫使其重新编译即可。 - node 从 0.12 版本开始,
socket.remoteAddress
的 IP 显示格式就变成了 IPv6 格式, 比如IP10.11.13.3
变为::ffff:10.11.13.3
- 清屏
/** 清屏 */ process.stdout.write('\x1b[2J'); /** 移动光标到左上角 */ process.stdout.write('\x1b[0f');
4. 代码规范
5. 项目瘦身
- nodejs项目在
npm i
之后, 会留下大量冗余的文件与中间编译文件 - 使用
npm ddp
来对单项目下的重复包进行冗余去除 - 对于多个项目, 把各个项目的node_modules移动到上层同一目录node_modules下, 去除单层重复包
- 部分包使用了gyp编译, 可去除其中间文件
- 去除各种冗余文件或文件夹, 比如“test” “example” “readme” “*.md” “.*ignore” “.travis.yml” “benchmark*” 等等.
6. Syntax
6.1 New
- What is the new keyword in javascript:
It is 4 things: It creates a new object. The type of this object, is simply object. It sets this new object's internal, inaccessible, [[prototype]] property to be the constructor function's external, accessible, prototype object (every function object automatically has a prototype property). It executes the constructor function, using the newly created object whenever this is mentioned. It returns the newly created object, unless the constructor function returns a non-primitive value. In this case, that non-primitive value will be returned.
new 相当于
function New(func) { var res = {}; if (func.prototype !== null) { res.__proto__ = func.prototype; } var ret = func.apply(res, Array.prototype.slice.call(arguments, 1)); if ((typeof ret === "object" || typeof ret === "function") && ret !== null) { return ret; } return res; }
所以
var sth = new func()
时, func()返回值而不是引用时, sth是func对象的新对象, 如果返回值为引用, 则sth为该引用.
6.2 JS的原型链
6.3 Tips
- 以变量为变量名
var name = 'some'; global[some] = 'thing'
,var name = 'some'; var name2={}; name2[name]='thing'
- 删除子对象
var obj = {name:'some',des:'thing'}; delete obj.des;
;删除对象则直接obj=null
会自动回收。 - 逻辑运算符“||”与“&&”,也遵循短路原则,但与其它很不同的一点是,其返回值并不是bool, 而是条件参
var name = 'some' && 'thing'; //name == 'thing' var name = false || 'thing'; //name == 'thing' var name = false && 'thing'; //name == false
- 对象的 clone :
var old = {a: 1, b: 2}; var new = Object.assign({}, old);// 可能不适用IE
- 如果文件 tt.log 被
fs.createWriteStream
以w+
的方式打开, 那么中途在另一进程里truncate -s0 tt.log
之后, 文件流仍然会继续在之前的位置写入 tt.log , 导致 tt.log 大小仍保持原大小,第一行变成了原长度的乱码。 所以有定期 truncate 的文件在写入时一定要使用a+
的方式来打开流。 详见man fopen
. 所以使用 forever-monitor 这个库时一定记得加上参数append:true
, 具体见库源码. - 如果字符串与数字比较,字符串会被转换成数字再进行比较:
console.log('9.99' > '10.00'); // true, => '9' > '1' console.log('9.99' > 10.00); // false, => 9.99 < 10.00 console.log('wtf9.99' > 10.00);// false, => 9.99 < 10.00
7. Debug
console.log()