rainit2006 / JS-room

javascript knowledge
0 stars 0 forks source link

NodeJS项目实战—仿cnodejs社区论坛 #6

Open rainit2006 opened 7 years ago

rainit2006 commented 7 years ago

https://www.youtube.com/watch?v=64_p8TXg-lI

rainit2006 commented 7 years ago

lodash javascrip工具库。 lodash(Underscore.js)を使用する目的 配列やオブジェクトの操作をする際に便利 コードの可読性アップ つまりコードをシンプルかつ短縮できる for文、if文を多用せずに済む つまり保守性が高い(変数の状態を知らなくて済む, 関数は参照透過性が保たれている)

常用方法: find, findindex, filter, pluck, map, remove, uniq

var _ =require("lodash");
var result = _.find(Users, {user:"zhangsan"});
Console.log(result);

//变换
_.map(Users, function(user){
    return {
              name:  user.name + xxxxx;
     }
});

//链式操作
Console.log(_chain(Users).map(xxxx).filter(xxxx).remove(xxx).value());
rainit2006 commented 7 years ago

eventProxy An implementation of task/event based asynchronous pattern. 解决javascript回调地狱问题。

常见方法:emit(发送消息), all(响应多个消息),after, fail, throw, done all 方法的监听器在满足条件之后 只会执行一次 tail 方法监听器 在满足条件之后,如果组合事件中的某个事件再次被触发,监听器会用最新的数据继续执行。 after()方法来实现事件在执行多次后 执行监听器的单一事件组合订阅方式

var fs=require("fs");
var EventProxy = require("eventProxy");

var ep = new EventProxy();
//fs.readFile("file1.txt", "utf8", function(err, content){
//  console.log(content)
//});

/*
/////all function//
ep.all(["read_file1","read_file2","read_file3"], function(content1, content2, content3){
    console.log(content1+content2+content3)
});

fs.readFile("file1.txt", "utf8", function(err, content1){
    ep.emit("read_file1", content1);
});

fs.readFile("file2.txt", "utf8", function(err, content2){
    ep.emit("read_file2", content2);
});

fs.readFile("file3.txt", "utf8", function(err, content3){
    ep.emit("read_file3", content3);
});
*/
/*
///////after function
ep.after("read_file", 3, function(contents){
    console.log(contents.join())
});

fs.readFile("file1.txt", "utf8", function(err, content1){
    ep.emit("read_file", content1);
});

fs.readFile("file2.txt", "utf8", function(err, content2){
    ep.emit("read_file", content2);
});

fs.readFile("file3.txt", "utf8", function(err, content3){
    ep.emit("read_file", content3);
});
*/

/*
/////fail function
ep.fail(function(err){
    console.log("this is a fail function:"+err);
});
//there are no file4.txt file, err must occur.
fs.readFile("file4.txt", "utf8", function(err, content3){
    if(err){
        ep.throw(err);
        //ep.emit("error", err);
    }
});
*/

///////after and done function
ep.after("read_file", 1, function(contents){
    console.log(contents.join())
});

//fs.readFile("file1.txt", "utf8", ep.done("read_file"));
fs.readFile("file1.txt", "utf8", ep.done("read_file", function(content){
    return content+"ooxxx";
}));
rainit2006 commented 7 years ago

ejs-mate 模板引擎

模板方法:layout,partial,block

layout(view)
  在模板中的任何位置调用此方法,会将此模板的内容套用在layout的<%- body -%>中。
partial(view, optionsOrCollection)
  当在模板中调用这个方法时,会将目标view的内容嵌套到当前的模板中,并表,可以通过optionsOrCollections将相关参数传递给目录view。
block('name')
  使用block('name')来创建一个块对象。这个块对象有4个方法,分别是append(),prepend(),replace()和toString()。

<%= 値 %> この記述は、<%= %>内に記述された値を出力します。 変数等を記述すれば、変数に格納された値を出力します。

<%- 値 %> この記述は、<%= %>と同じようなことを実現します。 違いは、HTMLタグを記述した場合に、<%= %>はエスケープ処理を行いますが、このタグはエスケープ処理を行いません。

エスケープ処理とは、
処理系によって特別な意味を割り振られる記号や文字列を、別の記号や文字列に置き換えること。例えば、HTMLで「<」を表示させる場合は「&lt;」と記述する。
rainit2006 commented 7 years ago

数据存储 MongoDB 是一个基于文档的数据库,所有数据是从磁盘上进行读写的。MongoDB善长的是对无模式JSON数据的查询。

而Redis是一个基于内存的键值数据库,它由C语言实现的,与Nginx/ NodeJS工作原理近似,同样以单线程异步的方式工作,先读写内存再异步同步到磁盘,读写速度上比MongoDB有巨大的提升。因此目前很多超高并发的网站/应用都使用Redis做缓存层,普遍认为其性能明显好于MemoryCache。当并发达到一定程度时,即可考虑使用Redis来缓存数据和持久化Session。

将Session存放到Redis中 connect-reids  是一个 Redis 版的 session 存储器,使用node_redis作为驱动。借助它即可在Express中启用Redis来持久化你的Session.

在实际项目中经常将express-session传给connect-redis来启用

var session = require('express-session');
var RedisStore = require('connect-redis')(session);

app.use(session({
    store: new RedisStore(options),
    secret: 'keyboard cat'
}));

检验

app.use(function (req, res, next) {
  if (!req.session) {
    return next(new Error('oh no')) // handle error
  }
  next() // otherwise continue
})

这样你的Session就转移到了Redis数据库,这样做的一个额外好处是,当你的Express服务器突然重启后,用户仍然可以使用当前Cookie中的SessionID从数据库中获取到他的会话状态,做到会话不丢失,在一定程度上提高网站的键壮性。

如果你的NodeJS网站上的所有缓存数据都转移到了Redis后,就可做到完全状态无关,按需扩展网站的规模。

查看redis server里的数据 使用redis-cli。

如果DB的ID指定为0之外,则选择DB: select 1。否则默认指定DB的index是0。
取得DB里保存的key数量: dbsize
获得Key的ID一览: keys *
显示某个key的内容:get “key的ID”
删除Redis里的DB所有内容: flushdb
退出: exit

Mongoose ode.js から MongoDB にアクセススためのライブラリ

Robomongo 管理查询MongoDB内容的工具,可以查看DB和Table内容等。

安装Redis server for Windows 下载地址:https://github.com/MSOpenTech/redis/releases 参考教程:http://keenwon.com/1275.html, https://my.oschina.net/lujianing/blog/204103

启动server时不要直接双击redis-server.exe,要用cmd启动redis-server.exe (会提示找不到config)文件 redis-server.exe redis.windows.conf

安装MongoDB server的business版(for windows) 从MongoDB官网上下载(需要注册个人信息) 安装和配置可以参考: http://qiita.com/boss_ape/items/e4c5024c00de25d3b1b6 要点: 创建log目录和log文件,以后有遇到问题可以看log文件的信息,很有用的。 创建data目录用以存放db数据。 创建config文件指定上述文件路径和ip/port等信息。

rainit2006 commented 7 years ago

顺序: 1,实现router和view Router目录下创建web_router.js文件。在里面,实现对get和post的响应-->即实现页面的跳转。 在app.js里,

var webRouter = require('./routes/web_router');
app.use('/', webRouter);

view里使用ejs模板

2,实现controller router里将get和post的响应函数交给controller实现。 router.get('/signup', signController.showSignup);

在controller里面去res.render( view画面 ); 或者 调用 数据Module的API。 exports.showSignup = fuction(req, res){ res.render('sign/signup') }

3, 编写数据模型Models 利用session, redis, mongodb来存储session,和数据模型Model。 app.js里

var session = require('express-session');
var RedisStore = require('connect-redis')(session);
...
app.use(session({
   secret:'adafdafafdaa',
   store: new RedisStore({
       port: 6379,
       host: '127.0.0.1'
   )),
   resave: true,
   saveUnintialized: true
}));

app.use(function(req, res, next){
    app.locals.current_user = req.session.user;  //current_user这个变量可以在view页面里被使用
    next();
});

创建models目录,在里面创建user.js文件

var mongoose = require('mongoose');
mongoose.connect('mongodb://127.0.0.1/node_club');

var UserSchema = new mongoose.Schema({ username: String, pass: String, email: String});
UserSchema.statics.getUserBySignupInfo = function(username, pass, email, callback){....}
,..
module.exports = mongoose.model('User', UserSchema);

在controller类(sign.js)里: var UserModel = require('../models/user'); 然后直接调用UserModel的函数来实现对user数据的操作。

rainit2006 commented 7 years ago

教程里的错误: html文件里,应该用typeof来判断某变量是否被定义,而不是type typeof(error) == 'undefine'

易犯错误: res和req弄混了。 比如要注意: req.session, req.body

rainit2006 commented 7 years ago

发表话题功能开发 引用js: markdownit.js, markdown-it.js (nodejs用) validator.js: validator.trim(),

路由层: 显示发表话题页面(get处理),提交话题信息(post处理),

评论功能开发 busboy.js: for parsing incoming HTML form data. 实现图片文件上传的处理。

function(req, res){ req.pipe(req.busboy); req.busboy.on('file', function(fieldname, file, filename, encoding, mimetype){ var newfilename = String((new Date()).getTime())+path.extname(filename); var filepath = __dirnam + '/../pulbic/upload/'+newfilename; var url = '/../pulbic/upload/'+newfilename; file.pipe(fs.createWriteString(filepath)); file.on('end', function(){ res.json({ success: true, url: url }); } ); }); }

path模块: