Project in May
from “I don’t care about performance, I just want it to work” to “thousands of people could be playing simultaneously, how do I scale?”
Project in May
using HTML template to generate pages
- Like using EJS, but it is just too simple to use, not recommeded by
single page web application p207
- using handlerbar.js(mustache.js), it cost about 120k, but with hogan.js, it only cost 2.5k
- last very popular way is to use jadeJs, which is defaultly embedded into node.js, also be supported natively by webstorm
Markdown is a good language to simply write something
- markdown file is the most used text file in github, which has a suffix of
md
- Wikipedia and Github have clear explanation, plus there are quick introduction here
Connect to MongoDB
- It is very convenient to connect to it in Heroku’s control panel
- Use Robomongo to access to it, here is a good tutorial.
- There is
_v
in mongodb database, which means version key explanation The version key is only incremented after operations that could cause a conflict, modifying array positions. Other updates won’t increment it.
Build Express module to support Auth
- Mainly according to the tutorial here
- Where I need to install body-parser from
npm install
, but here is a article says it may be create too much temp files. - Maybe you should not use body-parser anymore due to safty reason
- express-flash:define a flash message and render it without redirecting the request, require session and cookie-parser, which is just a flash show the info add to the screen, like formerlly you hide something and then it occurs, one difference in express4.0 is req.flash() (just use sessions: req.session.messages =
['foo']
or similar). I have thought about useing socket.io instead, but actually this flash use messages stored insession
- bcrypt-nodejs API.bcrypt是一个跨平台的文件加密工具。由它加密的文件可在所有支持的操作系统和处理器上进行转移。它的口令必须是8至56个字符,并将在内部被转化为448位的密钥。然而,所提供的所有字符都具有十分重要的意义。密码越强大,您的数据就越安全。
Passport Js
authentication and authorization authentication 仅仅是认证是本人 authorization 是授权可以做本人做的任何事
- 一旦认证成功,session将被建立,cookie将保存在客户端
- Each subsequent request will not contain credentials, but rather the unique cookie that identifies the session. In order to support login sessions, Passport will
serialize
anddeserialize
user instances to and from the session.之后的请求将都不会被要求认证,而是直接利用保存在客户端的cookie来确认身份,为了支持session,服务器端需要serialize and deserialize某些特定信息来确认是那一个用户(已认证成功的),‘’- passport.serializeUser(function(user, done) { done(null, user.id); });
passport.deserializeUser(function(id, done) { User.findById(id, function(err, user) { done(err, user); }); });
When Passport authenticates a request, it parses the credentials contained in the request. It then invokes the verify callback with those credentials as arguments, in this case username and password. If the credentials are valid, the verify callback invokes done to supply Passport with the user that authenticated. return done(null, user);
Here is a great stackoverflow answer on error handling. It explains how to use done() and how to be more specific with your handling of a route.
some problems:
how to signup with detailed information??
how to make html as response without the index.html on the link path??
app.get('/', function(req,res) {
res.sendfile('public/index.html');
});
process.nextTick()
On the next loop around the event loop call this callback. This is not a simple alias to setTimeout(fn, 0), it's much more efficient ,process.nextTick()的意思就是定义出一个动作,并且让这个动作在下一个事件轮询的时间点上执行。防止了一些情况下因为时间顺序导致的一些动作已经执行完,下面的被忽略的情况,[这里](http://www.cnblogs.com/lengyuhong/archive/2013/03/31/2987745.html)的例子很好
Express.render and sender
Use Handlebars as html template in Express
- use
npm install handlerbars --save
to install it -
use
npm install consolidate --save
to install consolidate, where in express official API doc has recommended.Some template engines do not follow this convention, the consolidate.js library was created to map all of node’s popular template engines to follow this convention, thus allowing them to work seemlessly within Express.
then in our server.js
var engines = require('consolidate');
app.set('view engine', 'html')
app.engine('html', engines.handlebars, function(err, html) {
if (err) throw err;
console.log("successful load handlebars engine");
});
//or direct use
//app.engine('html', engines.handlebars);
here is a good tutorial ###How to use key value map in javascript No standard method available. You need to iterate and you can create a simple helper:
Object.prototype.getKeyByValue = function( value ) {
for( var prop in this ) {
if( this.hasOwnProperty( prop ) ) {
if( this[ prop ] === value )
return prop;
}
}
}
var test = {
key1: 42,
key2: 'foo'
};
test.getKeyByValue( 42 ); // returns 'key1'
One word of caution: Even if the above works, its generally a bad idea to extend any host or native object’s .prototype. I did it here because it fits the issue very well. Anyway, you should probably use this function outside the .prototype and pass the object into it instead.
Another way is illustrate in this basic article
var associativeArray = {};
associativeArray["one"] = "First";
associativeArray["two"] = "Second";
associativeArray["three"] = "Third";
Express Page 404 Error Handling
basically
app.use(function(req, res, next){
res.status(404);
// respond with html page
if (req.accepts('html')) {
res.render('404', { url: req.url });
return;
}
// respond with json
if (req.accepts('json')) {
res.send({ error: 'Not found' });
return;
}
// default to plain-text. send()
res.type('txt').send('Not found');
});
For more detail on 500 and so on see here
My questions about
comparison bewteen HTTP protocal and web socket
Express req.locals
Response local variables are scoped to the request, thus only available to the view(s) rendered during that request / response cycle, if any. Otherwise this API is identical to app.locals.
This object is useful for exposing request-level information such as the request pathname, authenticated user, user settings etcetera.
app.use(function(req, res, next){
res.locals.user = req.user;
res.locals.authenticated = ! req.user.anonymous;
next();
});
Ligth box & Fancy box
use light box for some simple modal (min 9kb) while fancy box is suitable for image gallery because it could use mouse wheel to wheel over the pictures.(min 23kb) Here we may use leanModal totally instead of lightbox, coz it is only 1kb :)
JavaScript understanding
Funtion overloading
for(var prop in obj){
obj[prop] = i //set the key value property pari for "prop: i"
}
Check if a argument is offered by If(parameter === undefined)
arguments used for present all the input variable of a function.
It is a array, which is using by arguments[i]
hasOwnProperty()
Which could be used for check the property in the object, but not the prototyped property.
The difference between setInterval() and setTimeout() is large.
Should remember to use these two method to make asynchronous loading and heavy processing.
The HTML5 attribute async and defer only affect to asychronous downloading
But not affect to the asynchronous loading
Full page animation fullpage.js
Overwriting [fullPage](https://github.com/alvarotrigo/fullPage.js).js tooltip color
.fullPage-tooltip{
color: #AAA;
}
#fullPage-nav span, .fullPage-slidesNav span{
border-color: #AAA;
}
#fullPage-nav li .active span, .fullPage-slidesNav .active span{
background: #AAA;
}
here is CSS way to hidden scrollbar
.outer{
position: absolute;
bottom: 0;
top:0;
width: 100%;
overflow: hidden;
}
.inner{
width: 100%;
height: 100%;
padding-right: 15px;
overflow: scroll;
} see examples on [jsfiddle](http://jsfiddle.net/uB6Dg/1/) here
URI.JS
learn it maybe for the further use ======= But not affect to the asynchronous loading,
Difference between slice and substring
Notes on substring():
If start equals stop, it returns an empty string. If stop is omitted, it extracts characters to the end of the string. If start > stop, then substring will swap those 2 arguments. If either argument is greater than the string’s length, either argument will use the string’s length. If either argument is less than 0 or is NaN, it is treated as if it were 0. Notes on slice():
If start equals stop, it returns an empty string, exactly like substring(). If stop is omitted, slice extracts chars to the end of the string, exactly like substring(). If start > stop, slice() will NOT swap the 2 arguments. If either argument is greater than the string’s length, either argument will use the string’s length, exactly like substring(). If start is negative, slice() will set char from the end of string, exactly like substr() in Firefox. This behavior is observed in both Firefox and IE. If stop is negative, slice() will set stop to: (string.length – 1) – Math.abs(stop) (original value).
In short, that is
-slice和substring在正确使用的情况下用法相同
-substring 会自动转换错误的前后顺序,会自动调整超出的范围,slice也会调整,但是遇到负数
的情况,会有特殊处理。即从后往前数。
=== ###Mongoose - The Validator only works on saving progress, one problem is that you won’t know it is a internal database problem or a validation problem - Mongoose offer many ways for dealing with the find method, like findOneAndRemove, findOneAndUpdate, here is the example - testing date method
Path.find({ start: /stuttgart/i }, 'date', function (err, docs) {
var myDate = new Date();
docs = myDate;
console.log('time is'+docs.getTime()
+ 'day is' +docs.toDateString());
});
expiring property could be set as:
// expire in 24 hours
new Schema({ createdAt: { type: Date, expires: 60*60*24 }});
// expire in 24 hours
new Schema({ createdAt: { type: Date, expires: '24h' }});
// expire in 1.5 hours
new Schema({ createdAt: { type: Date, expires: '1.5h' }});
// expire in 7 days
var schema = new Schema({ createdAt: Date });
schema.path('createdAt').expires('7d');
Socket.io
####broadcasting
how to update certain client or all client? how to handle socket parameter? io.sockets.emit
or io.emit
may add something like of('/zugzug')
.
// socket is the *current* socket of the client that just connected
socket.emit('users_count', clients);
//Instead, you want to emit to all sockets
io.emit('users_count', clients);//
//sends a message to everyone except the socket that starts it
socket.broadcast.emit('users_count', clients);
find certain client
setting a map for the online sockets with certain id, if need to send message to it. first check the map, and then send to that client
//add
chatterMap [user_map._id] = socket;
//check
if (!chatterMap[result_map._id]) {
signIn(io, result_map, socket);
}
//find
if (chatterMap.hasOwnProperty(message.dest_id)) {
chatterMap[message.dest_id].emit('updatechat', message) ;//where the socket save
}
//delete
delete chatterMap[user_id];
//add some property to it
socket.user_id = result_map._id;
disconnect listener
client side: socket.disconnect(); server side : socket.on(‘disconnect’, function(){})
what about connect???
important change for express
when you introduce server, must change the app.listen(8080); to this server.listen(8080);
Autosave with user input
Main idea is to save the information according to the keyboard event of jquery, to the local cookies. - Simple implementation - with Sisyphus.js
blog comments powered by Disqus