我想学习nodejs 教程基础,麻烦说下哪有?

posts - 148,&
comments - 3,&
trackbacks - 0
nodeJs只是听说过,没见过,没玩过。从新手开始,我想慢慢掌握它。
一、首先,我想知道nodeJs是什么?
摘自百度百科:
Node.js是一套用来编写高性能网络服务器的JavaScript工具包,一系列的变化由此开始。比较独特的是,Node.js会假设在POSIX环境下运行Linux 或 Mac OS X。如果是在Windows下,那就需要安装MinGW以获得一个仿POSIX的环境。在Node中,Http是首要的。Node为创建http服务器作了优化,所以在网上看到的大部分示例和库都是集中在web上(http框架、模板库等)。
1. 用于服务器端;
2. 是一套javascript工具包;
3. 和http关系密切。
Node.js是一个可以快速构建网络服务及应用的平台。该平台的构建是基于Chrome's JavaScript runtime,也就是说,实际上它是对GoogleV8引擎(应用于Google Chrome浏览器)进行了封装。V8引擎执行Javascript的速度非常快,性能非常好。Node对一些特殊用例进行了优化,提供了替代的API,使得V8在非浏览器环境下运行得更好。例如,在服务器环境中,处理二进制数据通常是必不可少的,但Javascript对此支持不足,因此,V8.Node增加了Buffer类,方便并且高效地 处理二进制数据。因此,Node不仅仅简单的使用了V8,还对其进行了优化,使其在各环境下更加给力。
1. 是一个平台,可快速构建网络服务及应用;
2. 封装谷歌v8引擎。
Node.js 是服务器端的 JavaScript 运行环境,它具有无阻塞(non-blocking)和事件驱动(event-driven)等的特色,Node.js 采用 V8 引擎,同样,Node.js 实现了类似 Apache 和 nginx 的web服务,让你可以通过它来搭建基于 JavaScript 的 Web App。除此之外,nodejs还有很多有用的模块,可简化开发,比如向终端输出字符串。
nodeJs到底是啥?它不是js应用,而是服务器端js运行平台,即一个javascript的运行环境和库。可以编写系统级或者服务器端的Javascript代码,交给 Node.js来解释执行。就像html遇到php会由php解释器解释,jsp由jvm解释执行一样。
二、再者,它有哪些特性呢?
nodejs作为一个新兴的后台,有很多吸引人的地方:
RESTful API
Node.js可以在不新增额外线程的情况下,依然可以对任务进行并行处理 && Node.js是单线程的。它通过事件轮询(event loop)来实现并行操作,对此,我们应该要充分利用这一点 && 尽可能的避免阻塞操作,取而代之,多使用非阻塞操作。
解释如下:
事件驱动,在传统语言的网络编程中,我们会用到回调函数,比如当条件满足或是某事件发生时,注册的回调函数就会执行。Node.js的设计思想中以事件驱动为核心,它提供的绝大多数API都是基于事件的、异步的风格。以Net模块为例,其中的net.Socket对象就有以下事件:connectdata、end、timeout、drain、error、close等,使用Node.js的开发人员需要根据自己的业务逻辑注册相应的回调函数。这些回调函数都是异步执行的,这意味着虽然在代码结构中,这些函数看似是依次注册的,但是它们并不依赖于自身出现的顺序,而是等待相应的事件触发。事件驱动异步编程的设计,重要的优势在于,充分利用了系统资源,执行代码无须阻塞等待某种操作完成,有限的资源可以用于其他的任务。此类设计非常适合于后端的网络服务编程,Node.js的目标也在于此。在服务器开发中,并发的请求处理是个大问题,阻塞式的函数会导致资源浪费和时间延迟。通过事件注册、异步函数,开发人 员可以提高资源的利用率,性能也会改善。
三、具体可以干啥?
服务器端javascript应用,web应用等。
四、nodeJs环境搭建
windows下简单安装搭建可参考,其他系统安装可参看。
五、一个小实例
var http = require('http');
server = http.createServer(function (req, res) {
res.writeHeader(200, {"Content-Type": "text/plain"});
res.end("Hello oschina\n");
server.listen(8000);
console.log("httpd start @8000");
&确保nodejs环境安装成功,对以上文件编译执行通过,在浏览器地址栏输入localhost:8000,可以看到输出。
以上资料来自互联网,参考文档如下:
推荐几本nodejs书籍(csdn可下载):
阅读(...) 评论()node.js学习入门示例 - 隔壁老王 - ITeye技术网站
博客分类:
  这些天有点儿空闲,学习了一下node.js。先把《Node.js开发指南》书中的博客例子调通了,费了挺大的劲儿,因为好多插件出了新的版本,而新版本中有的函数、方法又失效了。
  自已又练习着做了一个例子,个人记账系统。主要是想在手机上用,所以界面做得很简单。
  解决了以下一些问题:express使用、bootstrap排版布局、mongodb模糊查询、mongodb统计(group/mapReduce)、session处理、req.flash方法使用等、路由设置等。花了不少的心思。
  例子中用到的插件的版本:
  connect-flash@0.1.1
  connect-mongo@0.4.0
  ejs@0.8.5
  express@3.4.8
  mongodb@1.3.23
  Bootstrap V3.0.3
  贴几张系统运行的图片,有图有真相嘛。
  核心代码贴一下:
一、app.js
* Module dependencies.
var express = require('express');
var http = require('http');
var path = require('path');
var util=require('util');
var routes = require('./routes');
//var User = require('./modules/user.js');
var settings=require('./Settings');
var MongoStore = require('connect-mongo')(express);
var flash = require('connect-flash');
var app = express();
//app.set('appTitle','老王个人记账系统');
app.locals.gAppTitle = settings.appN
//这个没有使用
app.locals.gPageSize = settings.pageS
// all environments
app.set('port', process.env.PORT || 8484);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.json());
app.use(express.bodyParser());
app.use(express.urlencoded());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(flash());
app.use(express.session({
"secret":settings.cookieSecret,
"store":new MongoStore({
db:settings.db
app.use(function(req, res, next){
//console.log("req.method="+req.method);
//console.log("req.url="+req.url);
//console.log("req.originalUrl="+req.originalUrl);
var url = req.originalU
//简单地定义一个登录拦截器
if ((url == "/month" || url=="/stat" || url=='/list' || url=='/record') && !req.session.user) {
console.log("登录拦截器提示:必须登录,才能执行此项操作。");
req.flash('error', '请先登录。');
return res.redirect("/login");
res.locals.user = req.session.
var error = req.flash('error');
res.locals.error = error.length?error:
//console.log("转移flash中的error值:"+error);
var success = req.flash('success');
res.locals.success = success.length?success:
//console.log("转移flash中的success值:"+success);
res.locals.session = req.
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
//console.log(util.inspect(app));
// development only
if ('development' == app.get('env')) {
app.use(express.errorHandler());
//console.log('注册路由.');
routes(app);
http.createServer(app).listen(app.get('port'), function(){
console.log();
console.log();
console.log('/**************************************************/');
console.log('/*
我的第一个NODE.JS例子。BY 隔壁老王
console.log('/*
欢迎访问我的博客:
console.log('/**************************************************/');
console.log('============服务启动成功,监听端口:' + app.get('port')+"============");
二、路由处理(routes\index.js)
var crypto = require('crypto');
var User = require('../modules/user.js');
var Consume = require('../modules/consume.js');
* GET home page.
module.exports = function(app) {
app.get('/',function(req, res){
res.render('index', { title: '首页' });
res.render('login',{
title:'用户登录',
//res.redirect('/login');
app.get('/record',function(req,res){
var user = req.session.
if(!user){
req.flash('error', '用户未登录,请登录。');
return res.redirect('/login');
Consume.get(user.name,{limit:16}, function(err, records) {
if (err) {
req.flash('error', err);
return res.redirect('/error');
res.render('record', {
title: user.name,
consumes: records,
//预处理,如果通过,再进行下一个。
app.post('/record',checkLogin);
app.post('/record', function(req, res) {
var currentUser = req.session.
var record = new Consume();
record.loadFromReq(currentUser.name, req.body);
record.save(function(err) {
if (err) {
req.flash('error', err);
return res.redirect('/');
req.flash('success', '发表成功');
res.redirect('/record');
//这个应该去掉。留在这里当个后门吧
//可以查看其他用户的数据
app.get('/u/:user', function(req, res) {
var username = req.params.
if (!username) {
req.flash('error', '未指定用户');
return res.redirect('/error');
Consume.get(username,{limit:0}, function(err, records) {
if (err) {
req.flash('error', err);
return res.redirect('/error');
console.log(records);
res.render('list', {
title: username,
consumes: records,
app.get('/del/:id', function(req, res) {
var id = req.params.
if (!id) {
req.flash('error', '未指定要删除的记录ID');
return res.redirect('/error');
console.log("准备删除记账记录,_id="+id);
Consume.del(id, function(err, records) {
if (err) {
req.flash('error', err);
return res.redirect('/error');
res.redirect('/record');;
app.get('/logout',function(req,res){
req.session.user =
req.flash('success','登出成功');
res.redirect('/login');
app.get('/list',function(req,res){
var user = req.session.
if(!user){
req.flash('error', "您没有登录,请登录。");
console.log("没有登录,重定向的登录界面。");
return res.redirect('/login');
Consume.get(user.name,{limit:0}, function(err, records) {
if (err) {
req.flash('error', err);
return res.redirect('/error');
res.render('list', {
title: user.name,
consumes: records,
app.post('/search',function(req,res){
var user = req.session.
if(!user){
req.flash('error', "您没有登录,请登录。");
return res.redirect('/login');
var keyword = req.body.
console.log("搜索关键字:"+keyword);
Consume.get(user.name,{limit:0,keyword:keyword}, function(err, records) {
if (err) {
req.flash('error', err);
return res.redirect('/error');
res.render('record', {
title: user.name,
consumes: records,
app.get('/stat',function(req,res){
var user = req.session.
Consume.stat(user.name, function(err, results) {
if (err) {
req.flash('error', err);
return res.redirect('/error');
res.render('stat', {
title: user.name,
results: results,
app.get('/month',function(req,res){
var user = req.session.
Consume.month(user.name, function(err, results) {
if (err) {
req.flash('error', err);
return res.redirect('/error');
res.render('stat', {
title: user.name,
results: results,
app.get('/error',function(req,res){
res.render('error');
//处理用户登录。
app.post('/login',function(req,res){
var md5=crypto.createHash('md5');
var password = md5.update(req.body.password).digest('hex');
User.get(req.body.username,function(err,user){
if(!user){
req.flash('error','用户不存在');
return res.redirect('/login');
if(user.password!=password){
req.flash('error','用户口令错误');
return res.redirect('/login');
req.session.user =
req.flash('success','登入成功');
//res.redirect('/');
res.redirect('/record');
app.get('/login',function(req,res){
res.render('login',{
title:'用户登录',
app.get('/reg',function(req,res){
res.render('reg',{
title:'用户注册'
app.post('/reg',function(req,res){
if(req.body['password-repeat']!=req.body['password']){
req.flash('error','两次输入的口令不一致!');
return res.redirect('/reg');
var md5=crypto.createHash('md5');
var password = md5.update(req.body.password).digest('hex');
var newUser = new User({
name:req.body.username,
password:password,
User.get(newUser.name,function(err,user){
err='同名用户已经存在,请更换名字.';
req.flash('error',err);
return res.redirect('/reg');
newUser.save(function(err){
req.error=
return res.redirect('/reg');
req.session.user = newU
req.flash('success','注册成功!');
res.redirect('/record');
//测试函数
app.get('/hello',function(req,res){
res.send('The time is '+new Date().toString());
//测试函数
app.get('/sayhello',function(req,res){
res.send('hello '+req.params.username);
//检查是否登入.
function checkLogin(req, res, next) {
if (!req.session.user) {
req.flash('error', '尚未登录,无法操作。');
return res.redirect('/error');
function checkNotLogin(req, res, next) {
if (req.session.user) {
req.flash('error', '已登入');
return res.redirect('/');
三、消费数据处理(modules\consume.js)
var mongodb = require('./db');
var BSON = require('mongodb').BSONP
var util=require('util');
function toObjectId(id){
console.log("转换值:"+id);
if( id=="" || id=="null" || id=="undefined" || id==undefined || id==null)
return BSON.ObjectID.createFromHexString(id);
function Consume(username, consumeDate,consumeSubject,consumeAmount,consumeRemark, time)
//加载时要单独赋值
this.userName =
this.consumeDate = consumeD
this.consumeSubject = consumeS
this.consumeAmount = consumeA
this.consumeRemark = consumeR
this.time =
this.time = new Date();
module.exports = C
Consume.prototype.loadFromReq = function loadFromReq(username,reqBody,time){
//自动进行了ID类型的转换。
this._id = toObjectId(reqBody._id);
this.userName =
this.consumeDate = reqBody.consumeD
this.consumeSubject = reqBody.consumeS
this.consumeAmount = reqBody.consumeA
this.consumeRemark = reqBody.consumeR
this.time =
this.time = new Date();
Consume.prototype.save = function save(callback)
// 存入 Mongodb 的文档
var record =
_id:this._id,
userName: this.userName,
consumeDate: this.consumeDate,
consumeSubject: this.consumeSubject,
consumeAmount: this.consumeAmount,
consumeRemark: this.consumeRemark,
time: this.time,
console.log('保存,记录日期:'+record.consumeDate);
mongodb.open(function(err, db){
return callback(err);
// 读取 posts 集合
db.collection('consume', function(err, collection){
mongodb.close(); return callback(err);
collection.insert(record, {safe: true} , function(err, post){
mongodb.close(); callback(err, post);
console.log("插入或更新,判断依据_id="+record._id);
if(record._id==null){
delete record._
console.log("删除_id,record._id="+record._id);
collection.update({_id:(record._id?record._id:'no-record')}, record, {upsert:true,multi:false} , function(err, post){
mongodb.close(); callback(err, post);
//删除方法
Consume.del = function del(id,callback){
mongodb.open(function(err,db){
return callback(err);
var query = {_id:BSON.ObjectID.createFromHexString(id)};
db.collection('consume', function(err, collection){
mongodb.close();
return callback(err);
collection.remove(query,{safe:true},function(err,result){
mongodb.close();
return callback(err);
console.log("删除成功。");
callback(null);
Consume.get = function get(username,options, callback)
mongodb.open(function(err, db){
return callback(err);
// 读取 posts 集合
db.collection('consume', function(err, collection){
mongodb.close();
return callback(err);
var query = {};
if(options.keyword){
//var regx = new RegExp("/"+options.keyword+"/");
//注意,不用/
var regx = new RegExp(options.keyword);
//限制用户名,科目或者金额与输入关键相等
query={"$and":[{userName:username},
{"$or":[{consumeSubject:regx},
{consumeDate:regx},
{consumeAmount:options.keyword}
query.userName =
console.log("搜索条件:");
console.log(query);
if(!options.limit){
options.limit=0;
collection.find(query).sort({consumeDate:-1 }).limit(options.limit).toArray(function(err, docs){
mongodb.close();
callback(err, null);
var consumes = [];
docs.forEach(function(doc, index){
var record = new Consume(doc.userName, doc.consumeDate,doc.consumeSubject,doc.consumeAmount,doc.consumeRemark, doc.time);
record._id = doc._
consumes.push(record);
callback(null, consumes);
Consume.stat = function stat(username, callback)
mongodb.open(function(err, db){
return callback(err);
// 读取 posts 集合
db.collection('consume', function(err, collection){
mongodb.close();
return callback(err);
var reduce = function(obj,prev){
prev.amount += isNaN(obj.consumeAmount)?0:Number(obj.consumeAmount);
prev.count++;
collection.group(
[ 'consumeSubject' ],
{userName:username},
{count:0,amount:0},
function(err, result){
mongodb.close();
callback(err, null);
console.log(result[0]);
var amount = 0,count=0;
result.forEach(function (item,index){
amount += item.
count += item.
result.push({consumeSubject:'【合计】',count:count,amount:amount});
callback(null, result);
Consume.month = function month(username, callback)
mongodb.open(function(err, db){
return callback(err);
// 读取 posts 集合
db.collection('consume', function(err, collection){
mongodb.close();
return callback(err);
var map = function(){
emit(this.consumeDate.substr(0,7),{amount:this.consumeAmount,count:1});
var reduce = function(key,vals){
var val = 0,count=0;
for(var i=0; i&vals.i++){
val += isNaN(vals[i].amount)?0:Number(vals[i].amount);
return {amount:val,count:count};
console.log("统计:"+username);
collection.mapReduce(
{out: {replace : 'temp', readPreference : 'secondary', query:{userName:username}}},
function(err, collection){
mongodb.close();
callback(err, null);
//console.log(collection);
var amount = 0,count=0;
result.forEach(function (item,index){
amount += item.
count += item.
result.push({consumeSubject:'【合计】',count:count,amount:amount});
var results = [];
collection.find().toArray(function(err,docs){
docs.forEach(function(item,idx){
console.log(item);
//为了共用结果页面,统一使用consumeSubject
results.push({consumeSubject:item._id,amount:item.value.amount,count:item.value.count});
mongodb.close();
callback(null, results);
  全部源码见附件。
  另,
  系统开发好了之后,找了个服务器部署了一下,老婆用得不错,原来不太喜欢记账,现在记账很积极。我就又把系统完善了一下,增加了翻页、权限控制功能,将几个按钮修改成图标,布局更紧凑了一些,使用全局变量保存系统名称,方便修改。
描述: 个人记账系统源码
下载次数: 315
(250.8 KB)
描述: 调试通过的书中例子
下载次数: 164
浏览: 1852976 次
来自: 北京
博主,我想问一下,我在ie上能打开,但是保存的时候并不是直接保 ...
“killpigman 写道请问Dbutils 怎样操作 已存 ...
写得真棒。我的IE浏览器经常出现缓存.
请问Dbutils 怎样操作 已存在的db 文件?
可能是connect-mongo的版本问题,我当时试着是好的。 ...今天看啥 热点:
Node.js学习笔记(一)—— Node基础,node.jsnode
欢迎转载,但请注明出处:http://blog.csdn.net/sysuzjz/article/details/
Node.js扫盲
Node.js有多种别称,Node,Nodejs,NodeJS。为了表示方便,文中会更频繁使用Node来表示。
为什么命名为Node呢?
一开始,创造者Ryan Dahl是称呼为web.js的,目的是构建一个web服务器。但后来项目发展越来越快,超出了单一的web服务器的想法,变成了构建网络应用的基础框架,在框架之上可以构建更多的东西,例如服务器、客户端、命令行工具等。它就像一个个节点,构成了各种网络应用,因此称为Node。
作为最近最热潮的后台语言,Node频繁的进入我们的视线。但就像一直有人搞不清楚Java和JavaScript的关系一样,很多人对Node也存在很多误解。比如:
Node肯定是几个前端工程师在实验室里鼓捣出来的为了后端而后端,有意思吗?怎么又发明了一门新语言?JavaScript承担的责任太重了直觉上,JavaScript不应该运行在后端前端工程师要逆袭了
实际上,JavaScript运行在后台并不是首例。在最开始诞生时,网景就开始尝试将它用在后端,微软也有样学样,这就是ASP中用的脚本语言。但当时JavaScript作为后端语言,性能无法与Java,PHP等相比,遂逐渐淡出众人视线。而现在,V8引擎、实时、高并发等优点让Node开始流行。
IO是很消耗时间跟性能的,众所周知JavaScript是单线程的,如果因为IO造成阻塞,性能将大打折扣。于是异步I/O应运而生了。将IO独立于主线程之外,只在IO完成后执行回调,效果类似于ajax。例如:
var fs = require(&js&);
fs.readFile(&/path&, function(err, file) {
console.log(&读取完成&);
console.log(&发起读取&);执行的顺序依次是:开始读取文件,输出&发起读取”,读取完成,输出“读取完成”。
回调何时执行是不可知的,我们只知道执行完IO会执行回调即可。这就是典型的不关系过程只关心结果。
DOM事件相信每一个写过前端的人都清楚,绑定完事件之后,只要触发事件,就能执行回调函数。这种做法是很高效的,因为我们不需要空转等待,或者说,我们把空转等待交给了更底层去实现。我们可以采用以下例子来说明,这个例子一般用于处理表单提交数据
var http = require(&http&);
http.createServer(function(request, response) {
var postData = &&;
request.on(&data&, function(trunk) {
postData +=
request.on(&end&, function() {
response.end(postData);
})我们分别给request对象添加data事件和end事件,前者是因为表单提交是分多次的,每次一项。后者意味着提交结束,输出接收到的表单项。
事件驱动具有轻量级、松耦合、只关注事务点等优势。
JavaScript是单线程的,Node当然也是单线程的。在Node中,JavaScript与其他线程无法共享任何状态。单线程最大的好处是不用像多线程编程那样处处在意状态的同步问题,一般情况下也不会出现死锁,也没有线程上下文交换所带来的性能上的开销。弱电也是有的,有以下三个方面:
无法利用多核CPU错误会引起整个应用退出,应用的健壮性值得考研大量计算占用CPU导致无法调用异步I/O
Node为解决这些问题采用了一个折中的办法:启用一个专门的并且完全独立的进程进行大量计算,计算完之后通过消息传递的方式传递运行结果。这就是child_process。工作思路和HTML5的Web Workers相同。
一开始Node只能在Linux下运行,后来和微软达成一致,实现了Windows平台的兼容。现如今,绝大部分主流平台都能完美支持Node。
Node的安装和部署
windows下直接在官网下载并安装即可:下载链接。windows下的node自带npm,可以用来安装各种模块
安装后检查node是否安装成功:
node -vnpm安装模块:以安装express为例:(-g表示全局安装)
npm install express -g
linux中,直接运行sudo apt-get install nodejs即可。
其他系统未测试,欢迎广大观众自行测试,并将结果以评论方式告知。
第一个Node程序
每一种编程语言的第一个程序都是hello world,我们这次也不要例外。
Node.js首先是JS其次才是Node,所以,我们先新建一个.js文件:server.js,在里面输入以下代码:
var http = require(&http&);
http.createServer(function(request, response) {
response.writeHead(200, {&Content-Type&: &text/plain&});
response.write(&Hello World&);
response.end();
}).listen(8888);第一行的require和python的import类似,都是引入新的模块,不同的是Node引入后返回一个对象。默认情况下,我们用模块名来命名模块对象,当然我们也可以换成其他名字,例如:
&pre name=&code& class=&javascript&&var foo = require(&http&);
foo.createServer(function(request, response) {
response.writeHead(200, {&Content-Type&: &text/plain&});
response.write(&Hello World&);
response.end();
}).listen(8888);
这样也是没问题的,但这里还是推荐用第一种命名方法。
创建服务器的方法是调用http模块的createServer方法,参数是一个函数,函数的参数分别为请求和响应。该方法返回结果仍然为对象,支持链式操作,后面是监听的端口号。
运行服务器时,我们先进入该js文件所在目录,运行node server.js,然后在浏览器中打开localhost:8888,我们会发现,浏览器中显示&Hello World&,服务器开启成功。
相关搜索:
相关阅读:
相关频道:
&&&&&&&&&&&&&&&&&&
WEB前端教程最近更新

我要回帖

更多关于 nodejs 教程 的文章

 

随机推荐