Nodejs
Nodejs 事件驱动 VS Java 多线程
单线程、多线程、事件驱动编程对比
在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。这种明确的执行顺序和串行化处理的行为是很容易推断得出的。如果任务之间并没有互相依赖的关系,但仍然需要互相等待的话这就使得程序不必要的降低了运行速度
在多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。与完成类似功能的同步程序相比,这种方式更有效率,但程序员必须写代码来保护共享资源,防止其被多个线程同时访问。多线程程序更加难以推断,因为这类程序不得不通过线程同步机制如锁、可重入函数、线程局部存储或者其他机制来处理线程安全问题,如果实现不当就会导致出现微妙且令人痛不欲生的bug。
在事件驱动版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。这种方式让程序尽可能的得以执行而不需要用到额外的线程。事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题。
当我们面对如下的环境时,事件驱动模型通常是一个好的选择
程序中有许多任务,而且…任务之间高度独立(因此它们不需要互相通信,或者等待彼此)而且… 在等待事件到来时,某些任务会阻塞。 当应用程序需要在任务间共享可变的数据时,这也是一个不错的选择,因为这里不需要采用同步处理。 网络应用程序通常都有上述这些特点,这使得它们能够很好的契合事件驱动编程模型。
时间,效率 对比
单线程,多线程,事件驱动编程,有Task1,Task2,Task3三个任务,灰色表示阻塞阶段
从下图可以看出,多线程的单条线程也是会有灰色的阻塞,而事件驱动编程没有阻塞的原因,暂且大致分析如下:事件队列是由一条线程去循环队列,如果是遇到I/O阻塞了这条唯一的线程,线程可能会分配一条协程来处理,线程继续循环。
- 进程:操作系统中分配资源的基本单位
- 线程:操作系统中调度资源的基本单位
- 协程:比线程更小的的执行单元,自带cpu上下文,一个协程一个栈

Nodejs 开发环境
window 下 进程查看
netstat -ano | find "LISTENING" | find "3000"
taskkill /f /im node.exe # f 代表强制终止
Centos7 NodeJs
Centos 安装Nodejs
yum
yum install nodejs npm # 不推荐,不是最新版本
官网下载对应OS 编译包
操作步骤:
- wget https://nodejs.org/dist/v10.16.0/node-v10.16.0-linux-x64.tar.xz
- xz -d node-v*
- tar -xf node
- mv node* /usr/local/nodejs/v10.16 //移动到你的管理目录
- ln -s 创建软链接 - ln -s /usr/local/nodejs/v10.16/bin/node /usr/bin/node - ln -s ***/npm /usr/bin/npm
- complete 验证 - node -v - npm -v
NPM node package manager
方便让JavaScript开发者下载、安装、上传以及管理已经安装的包.
npm install
npm install -h # 帮助命令
npm install [<@scope>/]<pkg>@<version range>
npm install --save-dev # 参数细节
npm install 在安装 npm 包时,有两种命令参数可以把它们的信息写入 package.json 文件,一个是npm install–save另一个是 npm install –save-dev,他们表面上的区别是–save 会把依赖包名称添加到 package.json 文件 dependencies 键下,–save-dev 则添加到 package.json 文件 devDependencies 键下,
不过这只是它们的表面区别。它们真正的区别是,npm自己的文档说dependencies是运行时依赖,devDependencies是开发时的依赖。即devDependencies 下列出的模块,是我们开发时用的,比如 我们安装 js的压缩包gulp-uglify 时,我们采用的是 “npm install –save-dev gulp-uglify ”命令安装,因为我们在发布后用不到它,而只是在我们开发才用到它。dependencies 下的模块,则是我们发布后还需要依赖的模块,譬如像jQuery库或者Angular框架类似的,我们在开发完后后肯定还要依赖它们,否则就运行不了。
npm init 初始化项目 package.json
npm ls
package.json 语法
常用的:
{
"name": "st-koa-web", //最重要的就是name和version字段。
//他们都是必须的,如果没有就无法install
"version": "1.0.0",
"description": "koa-study",
"main": "./src/app.js", //main字段配置一个文件名指向模块的入口程序。如果你包的名字叫foo,
//然后用户require("foo"),main配置的模块的exports对象会被返回。
//这应该是一个相对于根目录的文件路径。
"scripts": { //是一个由脚本命令组成的hash对象,他们在包不同的生命周期中被执行。
//key是生命周期事件,value是要运行的命令
"test": "test"
},
"config":{ //hash可以用来配置用于包脚本中的跨版本参数
"port":"8080"
}, //然后有一个“start”命令引用了npm_package_config_port环境变量,
//用户可以通过npm config set foo:port 8001来重写他
"repository": { //指定你的代码存放的地方
"type": "git",
"url": "git@lanbery:wiki-study/st-koa-web.git"
},
"author": "lanbery",
"license": "ISC",
"dependencies": { //依赖是给一组包名指定版本范围的一个hash
"koa": "^2.7.0",
"web3": "^1.0.0-beta.55"
}
"peerDependencies":{} // 解决项目直接使用间接依赖package里的功能
}
NB 的scripts 配置
{
// ...
"scripts": {
"build": "node build.js"
}
}
build命令对应的脚本是node build.js。 命令行下使用npm run命令,就可以执行这段脚本。
$ npm run build
# 等同于执行
$ node build.js
常用的配置
常用的简写
npm start是npm run start
npm stop是npm run stop的简写
npm test是npm run test的简写
npm restart是npm run stop && npm run restart && npm run start的简写
查看 包信息
npm info <包名> //查看包信息 npm view jquery version //查看jquery版本 ------包名>
node 引用本地未发布项目
两步:
- cd {workPath}/{project-A} && npm link
- cd {workPath}/{project-B} && npm link A
details
前端项目
webpack 项目结构参考
webpack 项目参考目录结构
* project
* node_modules //nodejs 自己管理的配置
* app //项目js文件,可细化模块
- main.js // 主入口js
- [**.js]
- moduleA 模块A
* public //静态H5
- index.html
* build
- bundle.js
- index.html build 生成 或copy
* package.json // nodejs 项目依赖
* webpack.config.js // 通过配置文件来使用Webpack
Centos7 源码安装 NodeJs
获取最新发行版
https://nodejs.org/download/release/latest/node-v12.9.1-linux-ppc64le.tar.gz
wget https://nodejs.org/download/release/latest/node-v12.9.1-linux-ppc64le.tar.gz
tar xzvf node-v12.9.1-linux-ppc64le.tar.gz && cd node-v*
-----
> npm script 环境变量的使用 顺便在加个排序;
拿到项目中 package.json 中显性的变量列表
"npm run env | grep npm_package | sort"
script 中使用
<code shell>
echo $npm_package_name
</code>
## NPM 采坑
- npm install --unsafe-perm -g web3 解决一堆乱七八糟错误
### Window kill
netstat -ano|findstr 9000
taskkill /pid pid -f
taskkill /im im -f
----
## 定义项目入口(main)
> ain 字段是 package.json 中的另一种元数据功能,它可以用来指定加载的入口文件。假如你的项目是一个 npm 包,当用户安装你的包后,require('my-module') 返回的是 main 字段中所列出文件的 module.exports 属性。当不指定main 字段时,默认值是模块根目录下面的index.js 文件
## 发布文件配置(files)
> files 字段用于描述我们使用 npm publish 命令后推送到 npm 服务器的文件列表,如果指定文件夹,则文件夹内的所有内容都会包含进来。我们可以查看下载的 antd 的 package.json 的files
```json
{
"files":[
"dist",
"lib",
"es"
]
}
module
它是 rollup 中最早就提出的概念 — pkg.module
webpack 从版本 2 开始也可以识别 pkg.module 字段。打包工具遇到 package1 的时候,如果存在 module 字段,会优先使用,如果没找到对应的文件,则会使用 main 字段,并按照 CommonJS 规范打包。所以目前主流的打包工具(webpack, rollup)都是支持 pkg.module 的,鉴于其优点,module 字段很有可能加入 package.json 的规范之中。另外,越来越多的 npm 包已经同时支持两种模块,使用者可以根据情况自行选择,并且实现也比较简单,只是模块导出的方式
browser,module,main 字段优先级
npm 包其实又分为:只允许在客户端使用的,只允许造服务端使用的,浏览器/服务端都可以使用
如果我们需要开发一个 npm 包同时兼容支持 web端 和 server 端,需要在不同环境下加载npm包不同的入口文件,显然一个 main 字段已经不能够满足我们的需求,这就衍生出来了 module 与 browser 字段
当存在 index.mjs 和 index.js 这种同名不同后缀的文件时,import ‘./index’ 或者 require(‘./index’) 是会优先加载 index.mjs 文件的
- main : 定义了 npm 包的入口文件,browser 环境和 node 环境均可使用
- module : 定义 npm 包的 ESM 规范的入口文件,browser 环境和 node 环境均可使用
- browser : 定义 npm 包在 browser 环境下的入口文件
----- lib
|-- index.browser.js
|-- index.browser.mjs
|-- index.js
|-- index.mjs
优先级依然是 browser = browser+mjs > module > browser+cjs > main

package 声明文件 types
{
"types":'./index.d.ts'
}
注意”typings”与”types”具有相同的意义,也可以使用它
同样要注意的是如果主声明文件名是index.d.ts并且位置在包的根目录里(与index.js并列),你就不需要使用”types”属性指定了
npm的“–force“和“–legacy-peer-deps“参数
f 或 –force:将强制 npm 获取远程资源,即使磁盘上存在本地副本也是如此
–legacy-peer-deps标志是在v7中引入的,目的是绕过peerDependency自动安装;它告诉 NPM 忽略项目中引入的各个modules之间的相同modules但不同版本的问题并继续安装,保证各个引入的依赖之间对自身所使用的不同版本modules共存