<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

EEPW首頁(yè) > 模擬技術(shù) > 設計應用 > 為什么向后端工程師推薦Node.js

為什么向后端工程師推薦Node.js

作者: 時(shí)間:2012-12-12 來(lái)源:網(wǎng)絡(luò ) 收藏

科普文一則,說(shuō)說(shuō)我對.的一些認識,以及我作為前端為什么會(huì )向后端推薦.。
. 是服務(wù)器端的 JavaScript 運行環(huán)境,它具有無(wú)阻塞(non-blocking)和事件驅動(dòng)(event-driven)等的特色,Node.js 采用V8引擎,同樣,Node.js實(shí)現了類(lèi)似 Apache 和 nginx 的web服務(wù),讓你可以通過(guò)它來(lái)搭建基于 JavaScript的Web App。”
我想不僅僅是Node.js,當我們要引入任何一種新技術(shù)前都必須要搞清楚幾個(gè)問(wèn)題:
1. 我們遇到了什么問(wèn)題?
2. 這項新技術(shù)解決什么問(wèn)題,是否契合我們遇到的問(wèn)題?
3. 我們遇到問(wèn)題的多種解決方案中,當前這項新技術(shù)的優(yōu)勢體現在哪兒?
4. 使用新技術(shù),帶來(lái)哪些新問(wèn)題,嚴重么,我們能否解決掉?
我們的問(wèn)題:Server端阻塞
Node.js被設計用來(lái)解決服務(wù)端阻塞問(wèn)題.下面通過(guò)一段簡(jiǎn)單的代碼解釋何為阻塞:

1
2
3
4
//根據ID,在數據庫中Persons表中查出Name
var name = db.query(select name from persons where id=1);
//進(jìn)程等待數據查詢(xún)完畢,然后使用查詢(xún)結果。
output(name)



這段代碼的問(wèn)題是在上面兩個(gè)語(yǔ)句之間,在整個(gè)數據查詢(xún)的過(guò)程中,當前程序進(jìn)程往往只是在等待結果的返回.這就造成了進(jìn)程的阻塞.對于高并發(fā),I/O 密集行的網(wǎng)絡(luò )應用中,一方面進(jìn)程很長(cháng)時(shí)間處于等待狀態(tài),另一方面為了應付新的請求不斷的增加新的進(jìn)程.這樣的浪費會(huì )導致系統支持QPS遠遠小于后端數據服 務(wù)能夠支撐的QPS,成為了系統的瓶頸.而且這樣的系統也特別容易被慢鏈接攻擊(客戶(hù)端故意不接收或減緩接收數據,加長(cháng)進(jìn)程等待時(shí)間)。
如何解決阻塞問(wèn)題
可以引入事件處理機制解決這個(gè)問(wèn)題。在查詢(xún)請求發(fā)起之前注冊數據加載事件的響應函數,請求發(fā)出之后立即將進(jìn)程交出,而當數據返回后再觸發(fā)這個(gè)事件并在預定好的事件響應函數中繼續處理數據:
1
2
3
4
5
6
//定義如何后續數據處理函數
function onDataLoad(name){
output(name);
}
//發(fā)起數據請求,同時(shí)指定數據返回后的回調函數
db.query(select name from persons where id=1,onDataLoad);



我們看到若按照這個(gè)思路解決阻塞問(wèn)題,首先我們要提供一套高效的異步事件調度機制.而主要用于處理瀏覽器端的各種交互事件的JavaScript。相對于其他語(yǔ)言,至少有兩個(gè)關(guān)鍵點(diǎn)特別適合完成這個(gè)任務(wù)。
為什么JS適合解決阻塞問(wèn)題
首先JavaScript是一種函數式編程語(yǔ)言,函數編程語(yǔ)言最重要的數學(xué)基礎是λ演算(lambda calculus) — 即函數對象可以作為其他函數對象的輸入(參數)和輸出(返回值)。
這個(gè)特性使得為事件指定回調函數變得很容易。特別是JavaScript還支持匿名函數。通過(guò)匿名函數的輔助,之前的代碼可以進(jìn)行簡(jiǎn)寫(xiě)如下:
1
2
3
db.query(select name from persons where id=1,function(name){
output(name);
});



還有另一個(gè)關(guān)鍵問(wèn)題是,異步回調的運行上下文保持(本文暫稱(chēng)其為”狀態(tài)保持”)。我們先來(lái)看一段代碼來(lái)說(shuō)明何為狀態(tài)保持:
1
2
3
4
5
6
7
//傳統同步寫(xiě)法:將查詢(xún)和結果打印抽象為一個(gè)方法
function main(){
var id = 1;
var name = db.query(select name from persons where id= + id);
output(person id: + id + , name: + name);
}
main();



前面的寫(xiě)法在傳統的阻塞是編程中非常常見(jiàn),但接下來(lái)進(jìn)行異步改寫(xiě)時(shí)會(huì )遇到一些困擾:
1
2
3
4
5
6
7
8
//異步寫(xiě)法:
function main(){
var id = 1;
db.query(select name from persons where id= + id,function(name){
output(person id: + id + , name: + name);//n秒后數據返回后執行回調
});
}
main();



細心的朋友可能已經(jīng)注意到,當等待了n秒數據查詢(xún)結果返回后執行回調時(shí)?;卣{函數中卻仍然使用了main函數的局部變量”id”,而”id”似乎應 該在n秒前走出其作用域。為什么此時(shí)”id”仍然可以訪(fǎng)問(wèn)呢,這是因為JavaScript的另外一個(gè)重要語(yǔ)言特性:閉包(Closures)。接下來(lái)我 來(lái)詳解閉包的原委。
在復雜的應用中,我們一定會(huì )遇到這類(lèi)場(chǎng)景。即在函數運行時(shí)需要訪(fǎng)問(wèn)函數定義時(shí)的上下文數據(注意:一定要區分函數定義時(shí)和函數運行時(shí)兩個(gè)不同的時(shí) 刻)。特別是在異步編程模型中,函數的定義和運行又分處不同的時(shí)間段,那么保持上下文的問(wèn)題變得更加突出了。因為我們在任務(wù)執行一半時(shí)把資源交出去沒(méi)有問(wèn) 題,但當任務(wù)需要再次繼續時(shí)我們必須還原現場(chǎng)。
在這個(gè)例子中,db.query作為一個(gè)公共的數據庫查詢(xún)方法,把”id”這個(gè)業(yè)務(wù)數據傳入給db.query,交由其保存是不太合適的。但我們可 以稍作抽象,讓db.query再支持一個(gè)需要保持狀態(tài)的數據對象傳入,當數據查詢(xún)完畢后可以把這些狀態(tài)數據原封不動(dòng)的回傳。如下:
1
2
3
4
5
6
7
8
9
function main(){
var id = 1;
var currentState = new Object();
currentState.person_id = id;
db.query(select name from persons where id= + id, function(name,state){
output(person id: + state.person_id + , name: + name);
},currentState);//注意currentState是db.query的第三個(gè)參數
}
main();



記住這種重要的思路,我們再看看是否還能進(jìn)一步的抽象?可以的,不過(guò)接下的動(dòng)作之前,我們還要了解在JavaScript中一個(gè)函數也是一個(gè)對象。 一個(gè)函數實(shí)例fn除了函數體的定義之外,我們仍然可以在這個(gè)函數對象實(shí)例之本身擴展其他屬性,如fn.a=1;受到這個(gè)啟發(fā)我們嘗試把需要保持的狀態(tài)直接 綁定到函數實(shí)例上:
1
2
3
4
5
6
7
8
9
10
function main(){
var id = 1;
var currentState = new Object();
currentState.person_id = id;
function onDataLoad(name){
output(person id: + onDataLoad.state.person_id + , name: + name);
}
onDataLoad.state = currentState ;//為函數指定state屬性,用于保持狀態(tài)
db.query(select name from persons where id= + id, onDataLoad);
}



我們做了什么?生成了currentState對象,然后在函數onDataLoad定義時(shí),將currentState綁定給 onDataLoad這個(gè)函數實(shí)例。那么在onDataLoad運行時(shí),就可以拿到定義時(shí)的state對象了。JavaScript的閉包特性就是內置了 這個(gè)過(guò)程而已。
在每個(gè)JavaScript函數運行時(shí),都有一個(gè)運行時(shí)內部對象稱(chēng)為Execution Context,它包含如下Variable Object(VO,變量對象), Scope Chain(作用域鏈)和”this” Value三部分。如圖:

上一頁(yè) 1 2 下一頁(yè)

關(guān)鍵詞: Node js 工程師

評論


相關(guān)推薦

技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>