nodejs瞎比比

nodejs自己随便写写

node全局对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
process是一个global全局对象,对于 Node.js 应用程序始终是可用的,故无需使用 require()
process提供了许多方法。
process.cwd() 返回当前工作目录。
process.platform 返回当前电脑的平台如:'darwin'

当然os模块也可以获取当前平台,os.platform(),os模块还可以获取其他信息

node中还有许多全局对象如:
__dirname: 全局变量,存储的是文件所在的文件目录
__filename:全局变量,存储的是文件名

全局对象还有setTimeout(cb, ms):全局函数在指定的毫秒(ms)数后执行指定函数(cb)
注意该函数可以使将同步操作改为异步操作。
console.log("1");
setTimeout(() => {console.log("2")}, 2);
setTimeout(() => {console.log("3")}, 0);
setTimeout(() => {console.log("4")}, 1);
setTimeout(() => {console.log("5")}, 0);
console.log("6")
clearTimeout(t)全局函数用于停止一个之前通过 setTimeout() 创建的定时器。 参数 t 是通过 setTimeout() 函数创建的定时器。
function printHello(){
console.log( "Hello, World!");
}
// 两秒后执行以上函数
var t = setTimeout(printHello, 2000);
// 清除定时器
clearTimeout(t);

setInterval(cb, ms)返回一个代表定时器的句柄值。可以使用 clearInterval(t) 函数来清除定时器。
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。

全局对象还有console 方法
console.log([data][, ...]):如果有多个参数,则 以类似于C 语言 printf() 命令的格式输出。
console.info
console.error输出错误消息的。控制台在出现错误时会显示是红色的叉子。
console.warn输出警告消息。控制台出现有黄色的惊叹号。

path

1
2
3
4
5
path.join()路径拼接
path.join('/a', '/b') // 'a/b'
path.join('./a', './b') // 'a/b'
path.resolve() 绝对路径 先pwd,在根据参数cd, cd后,最后pwd
path.resolve('./a', './b') // '/Users/Document/Projects/webpack-demo/a/b'

events

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
events模块只提供了一个对象: events.EventEmitter。EventEmitter 的核心就是事件触发与事件监听器功能的封装。
可以通过require("events");来访问该模块。
// 引入 events 模块
var events = require('events');
// 创建 eventEmitter 对象
var emitter = new events.EventEmitter();
emitter.on('someEvent', function(arg1, arg2) {
console.log('listener2', arg1, arg2);
});
emitter.emit('someEvent', 'arg1 参数', 'arg2 参数');
当然了addListener(event, listener)等价于on(event, listener):为指定事件注册一个监听器
once(event, listener):为指定事件注册一个单次监听器,即 监听器最多只会触发一次,触发后立刻解除该监听器。
removeListener(event, listener):移除指定事件的某个监听器,监听器必须是该事件已经注册过的监听器。
removeAllListeners([event]):移除所有事件的所有监听器, 如果指定事件,则移除指定事件的所有监听器。
listeners(event):返回指定事件的监听器数组。
emit(event, [arg1], [arg2], [...])执行指定监听器,如果事件有注册监听返回 true,否则返回 false

promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Node.js 异步编程的直接体现就是回调。
用在异步当中,防止层层嵌套回调。
const Q = require('q');

export class PromiseDemo {
static hello(name: string): Q.Promise<string> { //泛型string表示resolve的参数类型为字符串
let deferred = Q.defer();
if (name === "dottie") {
deferred.resolve(name + ' nihao');
} else {
deferred.reject(new Error("输入姓名不对"));
}
return deferred.promise;
}
}
PromiseDemo.hello('dottie')
.then(name => {
console.log(name)
}, error => {
console.log(error)
})

PromiseDemo.hello('dottie1')
.then(name => {
console.log(name)
}, error => {
console.log(error.message)
})

PromiseDemo.hello('dottie')
.then(value => {
console.log(value)
}, error => {
console.log(error)
})

exec和spawn

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 比如要运行 du -sh /disk1 命令, 
// 使用spawn函数需要写成spawn(‘du‘, [‘-sh ‘, ‘/disk1’]),
// 而使用exec函数时,可以直接写成exec(‘du -sh /disk1’)
// spawn是不支持callback函数,执行后就开始不断将数据从子进程返回给主进程,实时监控CPU,内存,IO,网络等数据。
let ls = spawn('ls', ['-a']);
ls.stdout.on('data', data => {
console.log("stdout" + data)
})
ls.stderr.on('data', data => {
console.log("stderr" + data)
})
ls.on('close', code => {
console.log("进程退出" + code);
})

// exec在子进程输出结果将放入buffer中,在结果返回完全之后,再将输出一次性地以回调函数参数的形式返回,有回调函数。
exec('ls -a', (err, stdout, stderr) => {
if (err) {
console.log("err" + err);
}
console.log("stdout::::" + stdout);
console.log("stderr::::" + stderr);
})

process.on('exit', function () {
setTimeout(function () {
console.log('This will not run');
}, 100);
console.log('node main process say Bye.');
});

path

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const path1 = require('path');
const fs1 = require('fs');

console.log(path1.sep);

// resolve 转换为绝对路径 先cd后pwd
let hellopath = path1.resolve('../demo', '../assets', 'hello.txt');
console.log("resolve" + hellopath); //resolve/Users/daejong/Desktop/yarn-port/src/assets/hello.txt
console.log(fs1.existsSync(hellopath)); //true
console.log(path1.extname(hellopath)); //.txt

let path2 = path1.join('../assets', '//hello.txt');
// 用于连接路径。该方法的主要用途在于,会正确使用当前系统的路径分隔符,Unix系统是"/",Windows系统是"\"。
console.log(path2); //../assets/hello.txt
console.log("hello");

typescript的ts文件中如果报找不到require关键字的话,需要安装下yarn add @types/node 即要require是在node模块中。

js和nodejs分析

js(偏向于前端浏览器): ecmascript(语法基础)+bom(操作浏览器)+dom(操作html页面元素)

nodejs(偏向后端):V8+ecmascript+os+fs+path+net+db+event等等

早期javascript是只能运行在浏览器中。而nodejs使得js脱离浏览器运行在后台。然后要想js运行在后台,首先要保证js要先被解释后正确的运行,而nodejs中就包含了google chrome的v8引擎(解释和运行js代码,非常高效),除此之外,nodejs中还提供了许多有用的模块,如os,fs, path,event, http模块等等。因此nodejs是基于chrome v8引擎的js的运行环境。同时他也是一个库。

而nodejs中一些模块的书写,当然要遵循一定的规范。如commonjs, amd,cmd规范。指定模块引用require,模块定义exports,模块标识module。而nodejs就是实现了这种规范。commonjs中一个单独的文件就是一个模块,每个模块都是一个单独的作用域,每个模块内部,都有一个module对象,代表当前模块。它有许多属性,常见就是exports标识模块的对外输出。还有模块的id,filename等等。

nodejs的特点:异步io,事件驱动,单线程。(用到callback和eventemitter)

还有nodejs默认使用npm包管理器进行管理依赖包。推荐是yarn吧(更快)。

typescript

js的超集,主要特点在js的动态语言的特性上添加type(类型),即提供给开发者在编译时就进行类型检查,避免了很多动态类型导致的莫名其妙的错误。当然了ts也提供了其他的新特性,如解构函数,数组值遍历for of,装饰器decorator,同时也提供了相对应的编译器tsc对ts文件进行编译成js代码。 默认使用es6中模块import和export的操作。

gulp自动化构建工具,利用好各种库(压缩文件,sass转css等等),定义好task及其顺序。既可以自动化构建。

nodejs

  1. fs.unlink(‘file’,callback), fs.mkdir(‘dir’,callback), fs.rmdir(‘dir’, callback)异步操作等等。
  2. 管道和流: 例子: ls | grep app 将ls的输出作为grep的输入。中间的|表示管道流stream的意思。nodejs所有的流都是eventemitter的实例。stdin, stdout, stderr,以及http的req,resp都是流。nodejs有一个流对象Stream。
  3. 读文件时readFile是将读到的数据一下子都放到的内存中,如何文件很大是就不适合用这种方式处理,这个时候就要用到stream。stream是把数据一边放到buffer中,一边处理。这样性能就会很高。

expressjs

熟悉下jade吧,express中默认的模板引擎。改名为了pug。支持模板继承extends和include语法简洁了不少。不用ejs模板引擎是是由于写ejs让我有一种之前写jsp的恶心<% %>,花括号满天飞。jade简直简洁的飞起。

layout.jade文件

1
2
3
4
5
6
7
8
9
10
11
doctype html
html
head
title= title
link(rel='stylesheet', href='/stylesheets/style.css')
block link
body.ui.container(style="padding: 20px")
block content
footer
hr
p @copyright dottie

view-> user.jade文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
extends layout
block link
link(rel="stylesheet", href="https://cdn.bootcss.com/semantic-ui/2.3.1/semantic.min.css")
block content
div.ui.dividing.header how do you do
p xi xi, learn express & jade -> pug
br
div.ui.primary.button 登录
div.ui.button#query 查询
div.ui.left.search.icon.focus.input
input(type='text', placeholder="search")
i.search.icon
table.ui.selectable.celled.striped.table.center.aligned.tablesorter#myTable
thead
tr
th name
th type
th award
tbody
- each row in data
tr
td #{row.name}
td= row.type
td= row.award

// 将js代码嵌入到jade中, 前面加上-表示代码中的特殊字符不会被转义, 使用=赋值代码中会转义, 使用!=赋值代码中不会被转义
- name = 'Bob'
if name == 'Bob'
h1 hello Bob
else
h1 My name is not Bob

h1 my name is #{name}
h2= 'hello <h3>world</h3>'
h3!= 'hello <h3>world</h3>'

script(src='https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js')
script(src='https://cdn.bootcss.com/jquery.tablesorter/2.30.3/js/jquery.tablesorter.min.js')
script(src='/javascripts/user.js')
script.
//自定义多行脚本等价于<script></script>

app.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
var createError = require('http-errors');
var express = require('express');
var path = require('path');
var cookieParser = require('cookie-parser'); //cookie操作中间件
var logger = require('morgan'); //HTTP请求日志中间件
const fs = require('fs');

var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// 记录http请求的日志到文件中。
var accessLog = fs.createWriteStream('./access.log', {flags : 'a'});
app.use(logger('dev')); ////打印到控制台
app.use(logger('combined', {stream : accessLog})); //打印到log日志
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', indexRouter);
app.use('/users', usersRouter);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
next(createError(404));
});

// error handler
app.use(function(err, req, res, next) {
// set locals, only providing error in development
res.locals.message = err.message;
res.locals.error = req.app.get('env') === 'development' ? err : {};

// render the error page
res.status(err.status || 500);
res.render('error');
});

module.exports = app;

db.js 用的mysql

1
2
3
4
5
6
7
8
9
const mysql = require("mysql")
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: '123456',
database: 'douban'
});

module.exports.connection = connection;

userService.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Q = require('q')
const db = require('../db')
// 使用q, 来优化回调函数书写的恶心
exports.queryAll = () => {
let deferred = Q.defer();
db.connection.query('select * from works', (err, rows, fields) => {
if (err) {
console.log(err);
deferred.reject(err);
}
// console.log(rows);
// console.log(fields);
deferred.resolve(rows);
})
return deferred.promise;
}

route-> users.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var express = require('express');
var router = express.Router();
const userService = require('../service/userService')

/* GET users listing. */
router.get('/', function(req, res, next) {
let promise = userService.queryAll();
promise.then((data) => {
console.log(data)
res.render('user', {data: data});
}, (err) => {
console.log(err);
})
// res.send('respond with a resource');
});

module.exports = router;

总体来说,express的web开发还是很简单的。