欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

node.js 一個(gè)簡(jiǎn)單的頁(yè)面輸出實(shí)現(xiàn)代碼

 更新時(shí)間:2012年03月07日 10:00:52   作者:  
最近決定重拾node.js,用它來做一個(gè)合并JS文件的東西。由于忘得差不多了,先看能不能輸出一個(gè)頁(yè)面來再說。以下是我的一些筆記,省得以后又忘凈光
安裝過程就不說了。如果成功是能使用node的命令。node.js調(diào)試是非常方便的。每種后臺(tái)語(yǔ)言都有一個(gè)向那個(gè)黑黢黢的控制臺(tái)團(tuán)輸出語(yǔ)用的命令。node.js沿用FF那套東西,也就是console對(duì)象與其方法。我們首先建一個(gè)example.js文件,內(nèi)容如下,然后在控制臺(tái)打開它。
復(fù)制代碼 代碼如下:

console.log("hello node.js")
for(var i in console){
console.log(i+" "+console[i])
}
node example.js。

你千萬(wàn)不要在node.js使用alert進(jìn)行調(diào)試,那是瀏覽器帶的全局方法,不報(bào)錯(cuò)才怪。
輸出結(jié)果如下:
復(fù)制代碼 代碼如下:

var log = function () {
process.stdout.write(format.apply(this, arguments) + '\n');
}
var info = function () {
process.stdout.write(format.apply(this, arguments) + '\n');
}
var warn = function () {
writeError(format.apply(this, arguments) + '\n');
}
var error = function () {
writeError(format.apply(this, arguments) + '\n');
}
var dir = function (object) {
var util = require('util');
process.stdout.write(util.inspect(object) + '\n');
}
var time = function (label) {
times[label] = Date.now();
}
var timeEnd = function (label) {
var duration = Date.now() - times[label];
exports.log('undefined: NaNms', label, duration);
}
var trace = function (label) {
// TODO probably can to do this better with V8's debug object once that is
// exposed.
var err = new Error;
err.name = 'Trace';
err.message = label || '';
Error.captureStackTrace(err, arguments.callee);
console.error(err.stack);
}
var assert = function (expression) {
if (!expression) {
var arr = Array.prototype.slice.call(arguments, 1);
require('assert').ok(false, format.apply(this, arr));
}
}

通過這些函數(shù),我們大概了解到node.js在全局作用域添加了些什么,如require, process。但也不能武斷說是,因?yàn)樗鼈兛赡苁悄硞€(gè)作用域的私有對(duì)象。不過,了解這些全局對(duì)象,并從這些對(duì)象上出發(fā)去了解其他對(duì)象,非常有助于我們了解node.js的生態(tài)結(jié)構(gòu)。在前端,每當(dāng)瀏覽器升級(jí),我就遍歷一下window對(duì)象以及其個(gè)元素節(jié)點(diǎn)就得知它又增加了什么方法與屬性,然后再查文檔。那些更新日志不可能把全部細(xì)節(jié)都告訴你的,必須自己動(dòng)手遍歷一下,這樣你就比別人知道得更多。好了,我們?nèi)フ襫ode.js的全局對(duì)象。
node.js的文檔告訴我們,有如下幾個(gè)全局對(duì)象:
global, process, require,__filename,__dirname, module
但我們?yōu)槭裁茨苤苯邮褂胏onsole.log呢?經(jīng)驗(yàn)告訴我們,console肯定是某全局對(duì)象的成員,正如我們可以alert, 也可以window.alert。好了,我們選遍歷一下global這個(gè)名字取得非常霸氣的對(duì)象
復(fù)制代碼 代碼如下:

for(var i in global){
console.log("var " + i+" = "+global[i])
}

結(jié)果如下:
復(fù)制代碼 代碼如下:

var global = [object global]
var process = [object EventEmitter]
var GLOBAL = [object global]
var root = [object global]
var Buffer = function Buffer(subject, encoding, offset) {
//太長(zhǎng)了,省略
}
var setTimeout = function () {
var t = NativeModule.require('timers');
return t.setTimeout.apply(this, arguments);
}
var setInterval = function () {
var t = NativeModule.require('timers');
return t.setInterval.apply(this, arguments);
}
var clearTimeout = function () {
var t = NativeModule.require('timers');
return t.clearTimeout.apply(this, arguments);
}
var clearInterval = function () {
var t = NativeModule.require('timers');
return t.clearInterval.apply(this, arguments);
}
var console = [object Object]

發(fā)現(xiàn)global與瀏覽器的window一樣,都有個(gè)指向自身的同名成員。window === window.window, global === global.global。但node.js早期設(shè)計(jì)得不好,又一搞了個(gè)多余的GLOBAL成員。
console.log(global === global.global)//true
console.log(global === global.GLOBAL)//true
我們?cè)俦闅vmodule對(duì)象:
復(fù)制代碼 代碼如下:

for(var i in module){
console.log("var " + i + " = "+module[i])
}

結(jié)果如下:
復(fù)制代碼 代碼如下:

var id = .
var exports = [object Object]
var parent = null
var filename = /home/cheng19840218/node/example.js
var loaded = false
var exited = false
var children =
var paths = /home/cheng19840218/node/node_modules,/home/cheng19840218/node_modules,/home/node_modules,/node_modules
var load = function (filename) {
//太長(zhǎng)了,省略
}
var _compile = function (content, filename) {
//太長(zhǎng)了,省略
}

原來那個(gè)著名的exports是在此提供的,__filename大概也是filename的引用。只要遍歷一下,你就發(fā)現(xiàn)許多有趣的東西。但別以為一下秘密就暴光在你眼皮下,還有許多不可遍歷屬性。比如上面我遍歷global對(duì)象,只有尞尞可數(shù)幾個(gè)成員,我們可以使用ecma262v5新增的方法去考察一下:
console.log(Object.getOwnPropertyNames(global))
結(jié)果如下:
復(fù)制代碼 代碼如下:

[ 'clearInterval',
'TypeError',
'decodeURI',
'Buffer',
'parseFloat',
'Number',
'URIError',
'encodeURIComponent',
'RangeError',
'ReferenceError',
'RegExp',
'Array',
'isNaN',
'setTimeout',
'console',
'Date',
'Infinity',
'Boolean',
'Error',
'root',
'NaN',
'String',
'Function',
'Math',
'undefined',
'encodeURI',
'escape',
'unescape',
'process',
'decodeURIComponent',
'EvalError',
'clearTimeout',
'GLOBAL',
'setInterval',
'SyntaxError',
'Object',
'eval',
'global',
'parseInt',
'JSON',
'isFinite' ]

許多人學(xué)node.js就立即看其文檔,殊不知node.js本身所依賴的V8引擎就擁有許多要學(xué)的東西,這其中包括ecma262v5帶來的新方法新對(duì)象,還有效仿firefox的一些語(yǔ)法:
__defineGetter__
__defineSetter__
__lookupGetter__
__lookupSetter__
set
get
__proto__
不過以"__"開頭的東西我是不建議用的,像set與get現(xiàn)在最新的瀏覽器都支持,如IE9,可以在其開發(fā)人員工具下試試下面的腳本:
復(fù)制代碼 代碼如下:

var a = {
get latest () {
if (this.log.length > 0) {
return this.log[this.log.length - 1];
}
else {
return null;
}
},
log: []
}
a.log[0] = "a";
a.log[1] = "b";
console.log(a.latest)

在node.js基本上沒有兼容問題(如果你不是從早期的node.js玩起來),而且原生對(duì)象又加了這么多擴(kuò)展,再加上node.js自帶的庫(kù),每個(gè)模塊都提供了花樣繁多的API,如果還嫌不夠,github上還有上千個(gè)插件。對(duì)于想向嘗試一下后端編程的JSer來說,這是極具誘惑力的。可能有人說,后端不是涉及數(shù)據(jù)庫(kù)操作嗎?這與比前端的DOM兼容比起來,不值一提。還有什么文件夾與文件操作 ,你就當(dāng)成是一種特殊的數(shù)組操作就是。因此你完全可以憤憤不平!
好了,我們來點(diǎn)實(shí)質(zhì)的內(nèi)容吧。node.js本來就是一個(gè)http服務(wù)器,它是要與前端交互的,因此少不了兩個(gè)對(duì)象:請(qǐng)求(request)與響應(yīng)(response)。請(qǐng)求與響應(yīng)顯然一種異步的東西,因?yàn)槲覀?不知道前端什么時(shí)候發(fā)請(qǐng)求過來,響應(yīng)也不能立即給前端,還要做日志,讀寫數(shù)據(jù)庫(kù)等操作呢。因此對(duì)于javascript來說,這用回調(diào)函數(shù)來實(shí)現(xiàn)最好。那么由誰(shuí)來接受這個(gè)回調(diào)呢?一個(gè)服務(wù)器對(duì)象!
復(fù)制代碼 代碼如下:

var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello node.js");
response.end();
}).listen(8888);

node.js有個(gè)特殊的require,用于同步加載其他模塊的對(duì)象,這與其他語(yǔ)言的require, import差不多。能同步就是好,不像前端那樣一層套一層。然后利用一個(gè)函數(shù)去實(shí)例化一個(gè)服務(wù)器對(duì)象,然后監(jiān)聽8888端口。這是node.js官網(wǎng)最初的例子,大家都寫爛了。但這樣的程序在現(xiàn)實(shí)中一無(wú)是處,我們?cè)诘刂窓谏陷斎險(xiǎn)RL,你起碼要返回一個(gè)完整頁(yè)面給我吧!
對(duì)此,我們首先要進(jìn)行模塊化。模塊化是以文件為單位的,把example.js更名為server.js,然后再把里面的內(nèi)容改為一個(gè)模塊。對(duì)于一個(gè)node.js的文件,其實(shí)它里面的內(nèi)容是在一個(gè)封閉的環(huán)境中執(zhí)行。要想共享給其他模塊使用,就必須綁定在exports對(duì)象上。
復(fù)制代碼 代碼如下:

var http = require("http");
exports.start = function(){
http.createServer(function(request, response) {
console.log("Request received...");
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hello node.js");
response.end();
}).listen(8888);
console.log("server start...");
}

然后我們?cè)俳ㄒ粋€(gè)index.js作為入口(index.js與server.js放在同一目錄下)。
復(fù)制代碼 代碼如下:

var server = require("./server");
server.start();

然后建一個(gè)index.html頁(yè)面。
復(fù)制代碼 代碼如下:

<!doctype html>
<html>
<head>
<title>index</title>
<meta content="IE=8" http-equiv="X-UA-Compatible"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

</head>
<body>
<h2>這是首頁(yè)</h2>
</body>
</html>

現(xiàn)在我們就在要請(qǐng)求過來時(shí),把此頁(yè)的內(nèi)容讀出來,返給用戶。這時(shí)我們就要用到fs模塊的方法了。
復(fù)制代碼 代碼如下:

var http = require("http");
var fs = require('fs');
exports.start = function(){
http.createServer(function(request, response) {
fs.readFile('./index.html', 'utf-8',function (err, data) {//讀取內(nèi)容
if (err) throw err;
response.writeHead(200, {"Content-Type": "text/html"});//注意這里
response.write(data);
response.end();
});
}).listen(8888);
console.log("server start...");
}

好了,這時(shí)我們重啟再次輸入地址,就看到一個(gè)完整的頁(yè)面了。
但一個(gè)頁(yè)面除了HTML結(jié)構(gòu)層外,還有javascript與css。那么,我們?cè)诋?dāng)前目錄建一個(gè)文件夾javascripts, 里面建index.js,內(nèi)容如下:
復(fù)制代碼 代碼如下:

window.onload = function(){
var p = document.createElement("p");
p.innerHTML = "這是動(dòng)態(tài)添加的"
document.body.appendChild(p);
}

再建一個(gè)styles目錄,里面建index.css,內(nèi)容如下:
復(fù)制代碼 代碼如下:

html,body{
background: #3671A5;
height: 100%
}

然后在index.html引入這兩個(gè)文件:
復(fù)制代碼 代碼如下:

<!doctype html>
<html>
<head>
<title>index</title>
<meta content="IE=8" http-equiv="X-UA-Compatible"/>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="styles/index.css"/>
<script src="/javascripts/index.js"></script>
</head>
<body>
<h2>這是首頁(yè)</h2>
</body>
</html>

重新打開,發(fā)現(xiàn)沒有改變,google,說要處理js與css文件的請(qǐng)求。沒有辦法,取得request.url屬性,再判定后綴名,為它進(jìn)行文件讀取與設(shè)置首部。
復(fù)制代碼 代碼如下:

var http = require("http");
var fs = require('fs');
var url = require('url');
exports.start = function(){
http.createServer(function(request, response) {
var pathname = url.parse(request.url).pathname;
var ext = pathname.match(/(\.[^.]+|)$/)[0];//取得后綴名
switch(ext){
case ".css":
case ".js":
fs.readFile("."+request.url, 'utf-8',function (err, data) {//讀取內(nèi)容
if (err) throw err;
response.writeHead(200, {
"Content-Type": {
".css":"text/css",
".js":"application/javascript",
}[ext]
});
response.write(data);
response.end();
});
break;
default:
fs.readFile('./index.html', 'utf-8',function (err, data) {//讀取內(nèi)容
if (err) throw err;
response.writeHead(200, {
"Content-Type": "text/html"
});
response.write(data);
response.end();
});
}
}).listen(8888);
console.log("server start...");
}

 
至此,本文的目的達(dá)到了。三個(gè)node.js文件,一個(gè)普通的js文件,一個(gè)css文件,一個(gè)html文件。下一個(gè)目的就是多頁(yè)了,一個(gè)網(wǎng)站是由多個(gè)目的構(gòu)成的。它包含如下內(nèi)容,能處理ajax請(qǐng)求,上傳文件,Session與Cookie支持,日志,MIME識(shí)別,路由派發(fā),緩存系統(tǒng)......要做的事多得嚇人,因此有人一上來就框架,與學(xué)JS那樣,連API還沒有摸熟就用jQuery了,那學(xué)個(gè)毛!回顧一下我們上面的server.js中間的部分,其實(shí)就要把MIME與路由拆分出來的。但最重要的事還有一樣,如何處理這無(wú)窮的函數(shù)嵌套?本人覺得這與我的模塊加載系統(tǒng)還沒有什么兩樣,下次就從這里動(dòng)手吧。

相關(guān)文章

最新評(píng)論