运行
node 是一个单进程单线程的东西。但是可以用回调来异步使用。
首先需要下载node.pkg 去官网下就行了。然后配置环境变量。把这个红框的加进去就行了。
/etc/profile /etc/paths ~/.bash_profile ~/.bash_login ~/.profile ~/.bashrc 这个是系统配置的路径。 当前配的~/.bash_profile
node.js 要想命令行运行一个js 就用 node xxx.js命令 node -v npm -v 看版本。
想创建一个项目没有package.json需要 npm init 这样就会创建一个 package.json 刚开始我以为这个是跟npm或者node绑定的一个json配置文件,后来发现这个东西是每一个项目都存在,都不一样的一个文件。你需要有这个文件才能使用 npm install xx 命令。
npm install 会在当前目录创建一个 node_modules 文件夹。这个就相当于你Java导的jar包似的。
要想命令行玩,node 进入命令行 然后该怎么编码怎么编码。
两下 control+c 退出命令行模式。
让我们先了解下 Node.js 应用是由哪几部分组成的:
1.引入 required 模块:我们可以使用 require 指令来载入 Node.js 模块。
2.创建服务器:服务器可以监听客户端的请求,类似于 Apache 、Nginx 等 HTTP 服务器。
3.接收请求与响应请求 服务器很容易创建,客户端可以使用浏览器或终端发送 HTTP 请求,服务器接收请求后返回响应数据。
所以一个node项目是需要写一个服务器的。
//我们使用 require 指令来载入 http 模块,并将实例化的 HTTP 赋值给变量 http
var http = require("http");
http.createServer(function (request,response) {
response.writeHead(200,{"Content-Type":"text/plain"});
response.end("hello zhanghong this is send message \n");
}).listen(8989);
console.log("server is running");
npm
npm -v 看版本。 sudo npm install npm -g 更新。 这个npm有种 maven的感觉。
npm install module_name 安装指定模块。 npm install xxx@1.1.0 指定版本号否则安最新的。 npm list 看导入的包。
npm有两种形式的安装。全局安装和非局部安装(本地安装)。
npm install module_name -g 差就差在这个 -g命令。
npm cache clear --force 清除本地缓存。
非全局的安装 需要你当前目录有package.json文件。没有会报错。 npm init 会在当前目录下创建package.json文件。
有了这个文件就可以安装node_modules了。
使用时用这个require命令来引入包。然后获取这个包的实例。通过实例来操作这个包的方法。var http = require("http");
这个个人理解的就像Java中 import包。但是这个导包需要有一个实例接收。这个实例能使用方法。可以理解为都是实例方法。
npm uninstall module 卸载模块。
这种方式的安装,只有这个项目是可见的。其他项目是看不见这个module。相当于Java中的maven。每个项目不一样。
全局安装 sudo npm install express -g 最好加sudo 要不可能会报错。可以看到我这个express模块全局安装到了npm同级目录。
下面还会做出关于全局非全局的叙述。
package.json
配置文件。首先这个里面不要写注释。会报错。 下面是属性说明。文末赋参考链接。
name 这个属性 要全部小写 无空格 version 就是 x.x.x 这样
keywords 这个关键字就是你在 npm search xxx 时候用的
main 入口函数。就像springboot中的 @springbootApplication注释的类似的。
script 默认有一个test. 这个是你 npm run xxx.js 来直接运行的。
dependencies 这个就是依赖的jar。相当于pom 可以指定版本号。生产环境。
devDependencies 这个是在开发环境上指定的jar。
关于dependencies中的jar的版本有一些说到。分为大版本,小版本,补丁版本。
如果允许随着版本的更新而更新前面就可以加一些符号。 ~表示接受补丁版本的更新,^表示接受小版本的更新,*表示接受大版本的更新,这个更新可能会存在一些问题,严重可能会导致你的接口随着版本的变更调不通。
~1.1.0 ^1.1.0 *
对于非全局的package.json。也就是你的项目中的package 里面的依赖通过 npm install 安装到 这个package关联的node_modules中。这个npm install 会安装所有的依赖到你的项目modules中。如果只安装dependencies的你可以用 npm install --production
所以在项目中最好拿过来先 npm install 一下、
install完了。你的modules中就有这些模块了。然后你就可以run了。在使用的地方通过 require() 引用实例。
对于全局的操作。命令加了 -g
注意:在你npm install module_name 安一个包后。你得在package中加入它。 或者你选择一个更酷的方式,用命令行。
npm install module_name --save 安装这个模块并把package.json中的dependencies也写上。
(--save-dev)是写到 devDependencies里。 下面是一个新的项目中。测试 save的例子。
先 npm init 在 npm install module_name --save 发现好用。
你也可以用npm update 来更新你的modules 但是注意你的package中的dependencies设置 ~ ^ * 否则更新不一定如愿。
REPL(交互式解释器)
这个简单运算就不说了。跟Java js 差不多。
提一下 _ 下划线。这个下划线是获取上一个表达式的结果。
回调函数
语法:function foo1(name, age, callback) { } function foo2(value, callback1, callback2) { }
var fs = require("fs");
var data = fs.readFileSync('input.txt');
console.log(data.toString());
console.log("程序执行结束!");
下面为创建过程与执行结果。
var fs = require("fs");
fs.readFile('input.txt', function (err, data) {
if (err){
console.log(err.stack);
return;
}
console.log(data.toString());
});
console.log("程序执行完毕");
这个是异步执行。回调函数 err参数是错误对象。执行异步操作的函数将回调函数作为最后一个参数, 回调函数接收错误对象作为第一个参数。
事件循环
通过events模块来操作事件。
var events = require('events'); //获取events实例
var eventEmitter = new events.EventEmitter();// 创建 eventEmitter 对象
这个eventEmitter 有两个操作。绑定事件。触发事件。
eventEmitter.on("eventName", eventHandler()); // 这个是声明eventName事件被触发时调用这个处理器。即执行eventHandler代码。这个相当于声明了一下,等待被emit触发。
eventEmitter.emit('eventName'); //这个是触发事件的意思。就是触发eventName事件。
例子 引自文末链接。
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var eventEmitter = new events.EventEmitter();
// 创建事件处理程序
var connectHandler = function connected() { //2.触发connection后调用这个处理器。
console.log('连接成功。'); //第一个输出。
// 触发 data_received 事件
eventEmitter.emit('data_received'); //触发data_received事件
}
// 绑定 connection 事件处理程序
eventEmitter.on('connection', connectHandler);
// 使用匿名函数绑定 data_received 事件
eventEmitter.on('data_received', function(){ //3.触发data_received事件调用这个处理器。
console.log('数据接收成功。'); //第二个输出
});
// 触发 connection 事件
eventEmitter.emit('connection'); //1.此处为第一次触发事件。触发connection
console.log("程序执行完毕。"); //第三个输出。
这个handler里面也可以设置形式参数。在emit的时候传入实参就行了。对于一个事件绑定的多个handler 按顺序执行。eventEmitter.listenerCount(''eventName"); 来获取这个事件的监听handler数量。
试想。要是一个事件触发另一个事件。另一个事件又触发这个事件,是不是就死循环了。
包括 fs、net、 http 在内的,只要是支持事件响应的核心模块都是 EventEmitter 的子类。
模块系统
node.js提供了exports和require 这两个对象来操作模块之间的联系。
其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口,即所获取模块的 exports 对象。
两个模块来说。就是俩js
first.js 代码如下。
function interfaceMethod() {
console.log("this is first method");
}
exports.interfaceFirst=interfaceMethod //暴露interfaceFirst 方法执行interfaceMethod处理器。
second.js
var first = require("./first");
first.interfaceFirst();
console.log("this is second js")
node second.js输出结果
路由
我们要为路由提供请求的 URL 和其他需要的 GET 及 POST 参数,随后路由需要根据这些数据来执行相应的代码。
server.js
var http = require('http');
var url = require('url');
console.log("access")
function startServer(route) {
function onRequest(request, response) { //这么写就得用路由访问了。要不执行不了。
var pathname = url.parse(request.url).pathname; //获取路径。
console.log("Request for " + pathname + " received.");
route(pathname); //将请求路径传入路由。
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello World");
response.end();
}
http.createServer(onRequest).listen(8888);//入参为function 也可以写匿名函数。由于使用路由就不用匿名函数了。
console.log("Server has started.");
}
exports.start = startServer; //模块间暴露接口start 调用本类的startServer
router.js
function route(pathname) {
console.log("About to route a request for " + pathname);
}
exports.routeMethod = route; //暴露路由的接口
index.js
var route = require("./router");
var server = require("./server");
console.log("this is index js")
server.start(route.routeMethod)
下面是输出的结果。可以看到先输出 access 也就是先进入服务器server类。执行到onRequest时阻塞 输出index类中的代码。然后输出server has received 可以看到 当我们没访问8888端口时 onRequest方法中没有输出。只是服务器启起来了。
下面是我分别访问 / /test 的结果。可以看出此时只要访问8888端口就会输出。所以这个pathname我们可以进行分发。
这个在使用express的web模块时会有很大的改善。包括 path的分发。可以参考 这个地址。
GET/POST
下面的类是用util的inspect方法获取到的URL所有能获取的信息
var http = require("http");
var url = require('url');
var util = require('util');
http.createServer(function (request,response) {
response.writeHead(200,{"Content-Type":"text/plain; charset=utf-8"});
response.end(util.inspect(url.parse(request.url, true)));
}).listen(8888);
一般HTTP请求常使用的是URL的query参数和body参数。下面是获取URL的 query参数
var http = require("http");
var url = require('url');
var util = require('util');
http.createServer(function (request,response) {
response.writeHead(200,{"Content-Type":"text/plain; charset=utf-8"});
var params = url.parse(request.url, true).query; //获取到查询参数。
response.write("网站名:" + params.name);
response.write("\n");
response.write("网站 URL:" + params.url);
response.end();
//util.inspect(url.parse(request.url, true))
}).listen(8888);
下面是body体的使用。
var http = require("http");
// var url = require('url');
// var util = require('util');
var querystring = require('querystring');
http.createServer(function(req, res){
// 定义了一个post变量,用于暂存请求体的信息
var post = '';
// 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中
req.on('data', function(chunk){
post += chunk;
});
// 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。
req.on('end', function(){
post = querystring.parse(post);
res.end(util.inspect(post));
});
}).listen(8888);
这部分就不多赘述了。
全局变量
在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性。
在 Node.js 我们可以直接访问到 global 的属性,而不需要在应用中包含它。
console.log("global >>>>>>" + global + "\n");
//表示当前正在执行的脚本的文件名。它将输出文件所在位置的绝对路径,且和命令行参数所指定的文件名不一定相同。 如果在模块中,返回的值是模块文件的路径
console.log("_filename >>>>>>" + __filename + "\n");
//_dirname 表示当前执行脚本所在的目录。
console.log("_dirname >>>>>>" + __dirname + "\n"); //注意是俩下划线。
var timer = setTimeout(function () {
console.log("this is setTimeout print" + "\n");
},1000) //单位ms
// clearTimeout(timer); //这个跟js用法差不多。
var timer2 = setInterval(function () {
console.log("this is setInterval print \n");
})
clearInterval(timer2);
// 还有 Process 这个属性能与OS交互。
下面是输出的结果。
Util类
这个类就像Java里面的util似的。是一个封装一些常用方法的工具类。
var util = require('util'); 需要引入这个模块。
说两个简单的用法吧。转成字符串输出 和 判断是不是数组。
var util = require('util');
var array = [1, 2, 3, 4, 5, 6]
var isArray = util.isArray(array);
console.log("is array ? >>>>>>" + isArray);
console.log("array >>>>>" + util.inspect(array))
AWS-Lambda + node.js 遇见的坑
关于错误截图就不加了,进行文字描述。
1.学习这个node.js 是有个需求做 echarts + canvas 的图片生成。于是我就开始接触这个东西。
第一个坑是按完不知道npm 咋用 就在一个随便的目录下使用npm install 然后发现报 not found package.json 类似错误。
然后发现得在该项目下面先 初始化 package.json 文件。 npm init 这样才能保证npm install 正常运行。
2.然后接下来就是装canvas 的一系列错。 打算把这个东西扔到 AWS-Lambda 上。这个部署包必须要求在 Linux环境下编译出来的。我之前是在 mac os 10.13 编译的 。扔上去就报错。然后放到 Linux 下面编译 还出了一系列问题。
第一个问题是 xxxx/dir permission 这么一个 错。 这样canvas 是装不成功的 。 我先 npm install --unsafe-perm 发现还是不行
于是我把这个项目中的 node_modules 设置成了 chmod -R 777 XXX 权限。 这个权限其实还是很有问题的。权限太高了。为了测试 这么提权后 确实可行。
3.然后我部署的时候又出现一个问题。就是 NODE_MODULE_VERSION 57 NODE_MODULE_VERSION 67 这么一个错误。这个错误就是编译版本不一致导致的 lambda 不能成功执行 node.js 代码 。于是我找到一个方法解决这个问题。 npm rebuild --abi=67 这样就编译指定二进制接口的版本。最后 zip 打包扔上去就好使了 。
4.还有一个问题就是这个lambda的返回结果是一个Json,所以是不能设置成content-type的。然后我是通过返回base64图片编码来解决这个事情。 前端还需要做相应的解码操作。
参考:https://blog.youkuaiyun.com/u011240877/article/details/76582670
声明:本文是在这个网站学习node.js记录下来的笔记。部分内容摘自: http://www.runoob.com/nodejs
刚刚入门这个node.js 因为常使用Java,然后有一个需求需要用到这个node.js就学习了一下。本文的内容还很浅。等有时间会深入了解一下这门语言。