nodejs

--摘自廖雪峯nodejs教程
javascript

No1:模塊html

var greet = require('./hello'); var s = 'Michael'; greet(s);
var s = 'Hello'; function greet(name){ console.log(s+','+name+'!') } module.exports = greet;

一個模塊想要對外暴露變量(函數也是變量),能夠用module.exports = variable;,一個模塊要引用其餘模塊暴露的變量,用var ref = require('module_name');就拿到了引用模塊的變量。java

Node利用JavaScript的函數式編程的特性,垂手可得地實現了模塊的隔離node

No2:git

JavaScript程序是由事件驅動執行的單線程模型,Node.js也不例外github

process.nextTick(function(){ console.log('nextTick callback'); }); process.on('exit',function(code){ console.log('about to exit with code: ' + code); }); console.log('nextTick was set');

結果web

nextTick was set nextTick callback about to exit with code: 0

process也是Node.js提供的一個對象,它表明當前Node.js進程express

No3:編程

fs--文件系統模塊,負責讀寫文件數組

異步讀取文件中的字符串

var fs = require('fs'); fs.readFile('sample.txt','utf-8',function(err,data){ if(err) { console.log(err); }else{ console.log(data) } });

同步讀取文件

var fs = require('fs'); var data = fs.readFileSync('sample.txt','utf-8'); console.log(data)

異步寫入文件

var fs = require('fs') var data = 'Hello,Node.js'; fs.writeFile('output.txt',data,function(err){ if(err){ console.log(err); }else{ console.log('ok.'); } });

同步寫入文件

var fs = require('fs'); var data = 'Hello,Node.js'; fs.writeFileSync('output.txt',data);

獲取文件的詳細信息

var fs = require('fs'); fs.stat('sample.txt',function(err,stat){ if(err){ console.log(err); }else{ //是不是文件
        console.log('isFile:'+stat.isFile()); //是不是目錄
        console.log('isDirectory:'+stat.isDirectory()); if(stat.isFile()){ //文件大小
            console.log('size:'+stat.size); //建立時間,Data對象
            console.log('birth time:'+stat.birthtime); //修改時間,Data對象
            console.log('modified time:'+stat.mtime); } } });

No4:

stream--流

讀取文件

var fs = require('fs') var rs = fs.createReadStream('sample.txt','utf-8') rs.on('data',function(chunk){ console.log('DATA:') console.log(chunk); }); rs.on('end',function(){ console.log('END'); }); rs.on('error',function(err){ console.log('ERROR:'+err); });

寫入文件

var fs = require('fs') var ws1 = fs.createWriteStream('output1.txt','utf-8'); ws1.write('使用Stream寫入文本數據...\n'); ws1.write('END'); ws1.end(); var ws2 = fs.createWriteStream('output2.txt'); ws2.write(new Buffer('使用Stream寫入二進制...\n','utf-8')); ws2.write(new Buffer('END.','utf-8')); ws2.end();

複製文件

var fs = require('fs'); var rs = fs.createReadStream('sample.txt'); var ws = fs.createWriteStream('copied.txt'); rs.pipe(ws);

No5:

http

服務器:

var http = require('http'); var server = http.createServer(function(request,response){ console.log(request.method+':'+request.url); response.writeHead(200,{'Content-Type':'text/html'}); response.end('<h1>Hello world!</h1>'); }); server.listen(8080); console.log('Server is running at http://127.0.0.1:8080/');

效果

文件服務器

var fs = require('fs'), url = require('url'), path = require('path'), http = require('http'); var root = path.resolve(process.argv[2] || '.'); console.log('Static root dir: '+root); var server = http.createServer(function(request,response){ var pathname = url.parse(request.url).pathname; var filepath = path.join(root,pathname); fs.stat(filepath,function(err,stats){ if(!err && stats.isFile()){ console.log('200'+request.url); response.writeHead(200); fs.createReadStream(filepath).pipe(response); }else{ console.log('404',request.url); response.writeHead(404); response.end('404 Not Found'); } }); }); server.listen(8080); console.log('Server is running at http://127.0.0.1:8080/');

效果

No6:

加密

const crypto = require('crypto'); const hash = crypto.createHash('md5'); // const hash = crypto.createHash('sha1');
hash.update('Hello,world!'); hash.update('Hello,nodejs!'); console.log(hash.digest('hex'));
const crypto = require('crypto'); const hmac = crypto.createHmac('sha256','secret-key'); hmac.update('Hello,world!'); hmac.update('Hello,nodejs!'); console.log(hmac.digest('hex'));

對稱加密

const crypto = require('crypto'); function aesEncrypt(data,key){ const cipher = crypto.createCipher('aes192',key); var crypted = cipher.update(data,'utf8','hex'); crypted += cipher.final('hex'); return crypted; } function aesDecrypt(encrypted,key){ const decipher = crypto.createDecipher('aes192',key); var decrypted = decipher.update(encrypted,'hex','utf8'); decrypted += decipher.final('utf8'); return decrypted; } var data = 'Hello,this is a secret message!'; var key = 'Password!'; var encrypted = aesEncrypt(data,key); var decrypted = aesDecrypt(encrypted,key); console.log('Plain text: '+data); console.log('Encrypted text: '+encrypted); console.log('Decrypted text:'+decrypted);

No7:

Koa

const Koa = require('koa'); const app = new Koa(); app.use(async(ctx,next)=>{ await next(); ctx.response.type = 'text/html'; ctx.response.body = '<h1>Hello,koa2!</h1>';
});

app.listen(3000);
console.log('app started at port 3000...');

koa把不少async函數組成一個處理鏈,每一個async函數均可以作一些本身的事情,而後用await next()來調用下一個async函數。咱們把每一個async函數稱爲middleware,這些middleware能夠組合起來,完成不少有用的功能。

app.use(async(ctx,next)=>{ console.log('${ctx.request.method} ${ctx.request.url}'); await next(); }); app.use(async(ctx,next)=>{ const start = new Date().getTime(); await next(); const ms = new Date().getTime() - start; console.log('Time:${ms}ms'); }); app.use(async(ctx,next)=>{ await next(); ctx.response.type='text/html'; ctx.response.body='<h1>Hello,koa2!</h1>'; });

No8:

koa-router

get請求

const Koa = require('koa'); const router = require('koa-router')(); const app = new Koa(); app.use(async(ctx,next)=>{ console.log(`Process ${ctx.request.method} ${ctx.request.url}...`); await next(); }); router.get('/hello/:name',async(ctx,next)=>{ var name = ctx.params.name; ctx.response.body = `<h1>Hello, ${name}!</h1>`;
}); router.get('/',async(ctx,next)=>{ ctx.response.body = '<h1>Index</h1>'; }); app.use(router.routes()); app.listen(3000); console.log('app started at port 3000...');

post請求

const Koa = require('koa'); const router = require('koa-router')(); const bodyParser = require('koa-bodyparser'); const app = new Koa(); app.use(async(ctx,next)=>{ console.log(`Process ${ctx.request.method} ${ctx.request.url}...`); await next(); }); app.use(bodyParser()); router.get('/',async(ctx,next)=>{ ctx.response.body = `<h1>Index</h1>
        <form action="/signin" method="post">
            <p>Name:<input name="name" value="koa"</p>
            <p>Password:<input name="password" type="password"></p>
            <p><input type="submit" value="Submit"></p>
        </form>`;
}); router.post('/signin',async(ctx,next)=>{ var name = ctx.request.body.name || '', password = ctx.request.body.password || ''; console.log(`signin with name:${name},password:${password}`); if(name==='koa' && password==='12345'){ ctx.response.body=`<h1>Welcome,${name}!</h1>`;
    }else{ ctx.response.body=`<h1>Loginfailed!</h1>
        <p><a href="/">Try again</a></p>`; } }); app.use(router.routes()); app.listen(3000); console.log('app started at port 3000...');

效果圖

No9:

koa-router

小型工程https://github.com/michaelliao/learn-javascript/tree/master/samples/node/web/koa/url2-koa

No10:

Nunjucks:模板引擎

小型工程https://github.com/michaelliao/learn-javascript/tree/master/samples/node/web/koa/use-nunjucks

No11:

單元測試

module.exports=function(...rest){ var sum = 0; for(let n of rest){ sum+=n; } return sum; }
const assert = require('assert'); const sum = require('./hello'); assert.strictEqual(sum(),0); assert.strictEqual(sum(1),0); assert.strictEqual(sum(1,2),3); assert.strictEqual(sum(1,2,3),6);
const assert = require('assert'); const sum = require('../hello'); describe('#hello.js', () => { describe('#sum()', () => { before(function () { console.log('before:'); }); after(function () { console.log('after.'); }); beforeEach(function () { console.log('  beforeEach:'); }); afterEach(function () { console.log('  afterEach.'); }); it('sum() should return 0', () => { assert.strictEqual(sum(), 0); }); it('sum(1) should return 1', () => { assert.strictEqual(sum(1), 1); }); it('sum(1, 2) should return 3', () => { assert.strictEqual(sum(1, 2), 3); }); it('sum(1, 2, 3) should return 6', () => { assert.strictEqual(sum(1, 2, 3), 6); }); }); });

異步測試

const fs = require('mz/fs'); // a simple async function:
module.exports = async () => { let expression = await fs.readFile('./data.txt', 'utf-8'); let fn = new Function('return ' + expression); let r = fn(); console.log(`Calculate: ${expression} = ${r}`); return r; };
const assert = require('assert'); const hello=require('../hello'); describe('#async hello',()=>{ describe('#asyncCalculate()',()=>{ it('#async with done',(done)=>{ (async function(){ try { let r = await hello(); assert.strictEqual(r,15); done(); } catch (err) { done(err); } })(); }); it('#async function',async()=>{ let r = await hello(); assert.strictEqual(r,15); }); it('#sync function',()=>{ assert(true); }); }); });

No12:

爲何WebSocket鏈接能夠實現全雙工通訊而HTTP鏈接不行呢?實際上HTTP協議是創建在TCP協議之上的,TCP協議自己就實現了全雙工通訊,可是HTTP協議的請求-應答機制限制了全雙工通訊。WebSocket鏈接創建之後,其實只是簡單規定了一下:接下來,我們通訊就不使用HTTP協議了,直接互相發數據吧。

const WebSocket = require('ws'); const WebSocketServer = WebSocket.Server; const wss = new WebSocketServer({ port: 3000 }); wss.on('connection',function(ws){ console.log(`[SERVER] connection`); ws.on('message',function(message){ console.log(`[SERVER] Received: ${message}`); setTimeout(()=>{ ws.send(`What's your name?`,(err)=>{ if(err){ console.log(`[SERVER] error:${err}`); } }); }); }) }); console.log('ws server started at port 3000...'); let count = 0; let ws = new WebSocket('ws://localhost:3000/ws/chat');
 ws.on('open',function(){ console.log(`[CLIENT] open()`); ws.send('Hello!'); }); ws.on('message',function(message){ console.log(`[CLIENT] Received: ${message}`); count++; if(count>3){ ws.send('Goodbye!'); ws.close(); }else{ setTimeout(()=>{ ws.send(`Hello,I'm Mr No.${count}!`); }); } });

效果

ws server started at port 3000... app.js:23 [SERVER] connection app.js:10 [CLIENT] open() app.js:30 [SERVER] Received: Hello! app.js:12 [CLIENT] Received: What's your name? app.js:35 [SERVER] Received: Hello,I'm Mr No.1! app.js:12 [CLIENT] Received: What's your name? app.js:35 [SERVER] Received: Hello,I'm Mr No.2! app.js:12 [CLIENT] Received: What's your name? app.js:35 [SERVER] Received: Hello,I'm Mr No.3! app.js:12 [CLIENT] Received: What's your name? app.js:35 [SERVER] Received: Goodbye! app.js:12 [SERVER] error:Error: not opened

歡迎關注個人微信公衆號:安卓圈

相關文章
相關標籤/搜索