詳解nodejs 文本操作模塊-fs模塊(五)
fs模塊是一個(gè)比較龐大的模塊,在前面也介紹了該模塊中最核心的一點(diǎn)東西,雖然核心的這點(diǎn)東西,在整個(gè)fs模塊中占據(jù)的比例比較小,但是如果只是我們平常使用的話,基本已經(jīng)夠用了,其他的一些方法,屬于能力提升時(shí)需要學(xué)習(xí)的的內(nèi)容了,所以在后面就不再繼續(xù)了,本篇屬于fs模塊中的最后一篇,也不是把fs模塊中的其他API都給一一列舉出來,這里再說最后一個(gè)我看來很重要的方法,監(jiān)聽文件或者目錄的的方法watchFile。
概總
這里之所以在最后把這個(gè)watchFile方法寫入到這里,是因?yàn)樵谇岸说囊粋€(gè)流行的構(gòu)建工具grunt中,有一個(gè)grunt-contrib-watch模塊,可以用于監(jiān)聽整個(gè)項(xiàng)目中,文件是否有變化,不知道有沒有人去看過該部分的源碼,是如何實(shí)現(xiàn)這個(gè)模塊的呢?(我是還沒有去看過,基礎(chǔ)學(xué)習(xí)完成之后,再去研究下)
所以,這里提前看下,fs模塊中的watchFile是如何實(shí)現(xiàn)的,等以后去看grunt中的watch模塊時(shí),就可以更得心應(yīng)手了,所以,想法和我相同的朋友們,就繼續(xù)看下去吧。。
fs.watchFile方法
該方法是用于監(jiān)聽指定文件的一個(gè)方法,其使用方法為
fs.watchFile(filename,[option],listener);
其中:
1:filename:必須,需要被監(jiān)聽的文件的完整的路徑以及文件名
2:option:可選,option支持兩個(gè)參數(shù),persistent屬性和interval屬性:
- interval屬性用于指定每隔多少毫秒監(jiān)聽一次文件的是否發(fā)生了改變,以及發(fā)生了什么改變,默認(rèn)為5007(毫秒)
- persistent屬性,用于指定了,當(dāng)指定了被監(jiān)視的文件后,是否停止當(dāng)前正在運(yùn)行的應(yīng)用程序,默認(rèn)為true
3:listener:必須,被監(jiān)聽文件發(fā)生改變時(shí)調(diào)用的回調(diào)函數(shù)
回調(diào)函數(shù)傳入兩個(gè)參數(shù)callback(curr,prev),它們都是fs.Stats的實(shí)例,關(guān)于該實(shí)例的詳細(xì)介紹,請參考前篇文章,curr表示修改之后的的信息對象,prev表示本次修改之前的信息對象。
下面看下,一個(gè)示例:
var fs = require("fs"); fs.watchFile("./message.txt",function(curr,prev){ if(Date.parse(prev.ctime) == 0){ console.log("message.txt被創(chuàng)建"); }else if(Date.parse(curr.ctime) == 0){ console.log("message.txt被刪除"); }else if(Date.parse(prev.mtime) != Date.parse(curr.mtime)){ console.log("message.txt被修改"); } });
運(yùn)行上述代碼,然后在與你.js的文件的同目錄下,進(jìn)行操作,創(chuàng)建message.txt,修改,刪除等操作,來查看控制臺的顯示。這只是一個(gè)簡單的演示,如果需要其他的數(shù)據(jù),那么就可以查看curr和prev中,能攜帶的數(shù)據(jù),然后根據(jù)不同的數(shù)據(jù),完成不同的操作。也就自己實(shí)現(xiàn)一些插件的功能。
當(dāng)然,也可以通過設(shè)置option的屬性值,使用不同的配置來監(jiān)聽對應(yīng)的文件,這里關(guān)于配置新的示例,就不再占用篇幅了,有興趣的可以自己測試一下。
watchFile的源碼實(shí)現(xiàn)
看完了示例,接下來就是源碼了,只有了解了最根本的源碼實(shí)現(xiàn),才能更好更高效的使用對應(yīng)的API,請認(rèn)真看源碼中的注釋:
// Stat Change Watchers // StatWatcher構(gòu)造函數(shù)定義 function StatWatcher() { //把EventEmitter內(nèi)部的實(shí)例化屬性添加到this對象上去。 //而EventEmitter的原型鏈屬性和方法,不會(huì)被添加到this對象 //所以,基本上,也就是把EventEmitter實(shí)例中的domain,_events,_maxListeners這三個(gè)屬性 //添加到了this對象上去了。 EventEmitter.call(this); //把this緩存到self變量中,便于下面的閉包回調(diào)使用該創(chuàng)建閉包時(shí)的this對象 var self = this; //調(diào)用C++實(shí)現(xiàn)的StatWatcher構(gòu)造函數(shù),并把返回的對象,賦值到this對象的_handle屬性上 this._handle = new binding.StatWatcher(); // uv_fs_poll is a little more powerful than ev_stat but we curb it for // the sake of backwards compatibility var oldStatus = -1; //當(dāng)C++中實(shí)現(xiàn)的StatWatcher實(shí)例化后的對象,定義它的onchange事件。 // 我測試過new binding.StatWatcher();實(shí)例化之后,是沒有onchange屬性的 // 所以,這里應(yīng)該是屬于直接定義改屬性的,那么定義之后,在nodejs的C++代碼實(shí)現(xiàn)中 // 是如何判斷這個(gè)屬性存在,然后在符合一定的條件下,又去執(zhí)行這個(gè)屬性的呢? // 這是我疑惑的地方,這個(gè)需要當(dāng)學(xué)習(xí)到更多這方面的知識后,再去了解一下。 // 經(jīng)過我的測試,這個(gè)屬性,是在實(shí)例的start執(zhí)行時(shí)需要的,如果沒有定義該屬性 // 那么,在使用start方法,開始監(jiān)聽事件時(shí),會(huì)被拋出異常的 // 拋出異常,是因?yàn)槟惚O(jiān)聽的文件,當(dāng)前不存在~~ // 如果監(jiān)聽的文件,當(dāng)前已經(jīng)存在,則不會(huì)執(zhí)行onchange的回調(diào) this._handle.onchange = function(current, previous, newStatus) { // 當(dāng)實(shí)例被話之后,當(dāng)被監(jiān)聽的文件,被更改時(shí),都會(huì)觸發(fā)該屬性的回調(diào)函數(shù) // 并且傳入三個(gè)參數(shù) // 這里的三個(gè)判斷,當(dāng)前不知道為什么會(huì)在這個(gè)時(shí)候,不執(zhí)行~~ if (oldStatus === -1 && newStatus === -1 && current.nlink === previous.nlink) return; oldStatus = newStatus; // 觸發(fā)self對象的中的change事件,并且把current和previous對象, // 傳入到change事件的回調(diào)函數(shù) // 在本構(gòu)造函數(shù)內(nèi)部,是沒有繼承EventEmitter構(gòu)造函數(shù)原型鏈中的方法的 // 但是這里,卻使用了原型鏈中的emit方法。why? self.emit('change', current, previous); }; this._handle.onstop = function() { self.emit('stop'); }; } // 把EventEmitter原型鏈的屬性和方法,擴(kuò)展到StatWatcher對象的原型鏈中 // 更確切的說明就是,StatWatcher.prototype = EventEmitter.prototype; util.inherits(StatWatcher, EventEmitter); // 在StatWatcher重新定義來原型鏈之后,再執(zhí)行其他的擴(kuò)展,以防止原型鏈斷鏈的情況 StatWatcher.prototype.start = function(filename, persistent, interval) { nullCheck(filename); this._handle.start(pathModule._makeLong(filename), persistent, interval); }; StatWatcher.prototype.stop = function() { this._handle.stop(); }; //緩存Watcher的一個(gè)對象 var statWatchers = {}; function inStatWatchers(filename) { //判斷filename是否在statWatchers中,如果是則返回緩存的實(shí)例 return Object.prototype.hasOwnProperty.call(statWatchers, filename) && statWatchers[filename]; } fs.watchFile = function(filename) { //判斷fileName是否合法 //如果不合法,則拋出一個(gè)異常然后停止執(zhí)行 nullCheck(filename); //調(diào)用path模塊的方法,返回文件的絕對路徑 filename = pathModule.resolve(filename); var stat; var listener; //默認(rèn)的配置信息,這里也說明來下,為何監(jiān)聽間隔為5007ms, //只是,我表示,我是沒有看懂下面的英文注釋要說啥的 var options = { // Poll interval in milliseconds. 5007 is what libev used to use. It's // a little on the slow side but let's stick with it for now to keep // behavioral changes to a minimum. interval: 5007, persistent: true }; //對參數(shù)進(jìn)行判斷,判斷是否有自定義的option,如果有,使用自定義的 //沒有定義的,使用默認(rèn)值 //回調(diào)函數(shù)賦值 if (util.isObject(arguments[1])) { options = util._extend(options, arguments[1]); listener = arguments[2]; } else { listener = arguments[1]; } //回調(diào)函數(shù)是必須的,如果沒有回調(diào)函數(shù),則直接拋出一個(gè)異常,并停止運(yùn)行 if (!listener) { throw new Error('watchFile requires a listener function'); } //看完上面的inStatWatchers的源碼之后,覺得這里是否可以再次優(yōu)化一次? //stat =inStatWatchers(filename); //if(!stat){ //stat = statWatchers[filename] = new StatWatcher(); //stat.start(filename,options.persistent,options.interval); //} //這樣的話,就可以節(jié)省一次對象的查找和取值了 //判斷該文件,是否已經(jīng)創(chuàng)建了StatWatcher實(shí)例 if (inStatWatchers(filename)) { //如果之前已經(jīng)創(chuàng)建過了,則使用之前創(chuàng)建過的StatWatcher實(shí)例 stat = statWatchers[filename]; } else { //如果沒有,則 重新創(chuàng)建一個(gè),并把創(chuàng)建的示例,保存下來 //用于接下來的,玩意又對該文件再次添加watchFile時(shí),使用 stat = statWatchers[filename] = new StatWatcher(); //并且,對實(shí)例執(zhí)行start的方法,應(yīng)該是啟動(dòng)該實(shí)例不 stat.start(filename, options.persistent, options.interval); } //對該實(shí)例,監(jiān)聽change事件,并設(shè)置回調(diào)函數(shù) stat.addListener('change', listener); return stat; };
注:在前面的源碼解釋中,出現(xiàn)了幾個(gè)概念,我認(rèn)為是有必要在這里補(bǔ)充一下的,因?yàn)槿绻麑@幾個(gè)概念的了解不深刻,那么久可能不理解為什么會(huì)這么寫,或者意識不到,必須這么寫才能保證代碼正確的執(zhí)行的。
1:只繼承實(shí)例內(nèi)部屬性和方法,涉及代碼:EventEmitter.call(this);
2:原型鏈的斷鏈概念,涉及代碼:util.inherits(StatWatcher, EventEmitter);
上述兩個(gè)概念的一些相關(guān)內(nèi)容,請參考:對象繼承的方法小結(jié),原型鏈斷鏈的原因,淺析賦值表達(dá)式–JS基礎(chǔ)核心之一。
3:nodejs中的event模塊,也就是EventEmitter構(gòu)造函數(shù)的相關(guān)信息:nodejs核心模塊–events。
4:util模塊,也就是util.inherits所在的模塊,nodejs核心模塊–util。
關(guān)于watchFile的源碼,到這也就結(jié)束了,接下來,看unwatchFile的方法,用于解除對某個(gè)文件的監(jiān)聽。
fs.unwatchFile方法
該方法是用于解除一個(gè)文件的監(jiān)聽事件,其使用方法為
fs.unwatchFile(filename,[listener]);
其中:
1:filename:必須,需要被監(jiān)聽的文件的完整路徑以及文件名
3:listener:可選,被監(jiān)聽文件發(fā)生改變時(shí)調(diào)用的回調(diào)函數(shù)
回調(diào)函數(shù)傳入兩個(gè)參數(shù)callback(curr,prev),它們都是fs.Stats的實(shí)例,關(guān)于該實(shí)例的詳細(xì)介紹,請參考前篇文章,curr表示修改之后的的信息對象,prev表示本次修改之前的信息對象。
這里不在給出示例了,其實(shí)unwatchFile就相當(dāng)于我們常用的off事件(jQuery),所以,這里也有個(gè)相同的問題,那就是,如果您不指定listenter的話,那么會(huì)把之前綁定的所有的watchFile的回調(diào)函數(shù),都去除掉的,再者,匿名函數(shù),是無法單獨(dú)解除綁定的,所以請注意。
fs.unwatchFile源碼
unwatchFile的實(shí)現(xiàn)原理是比較簡單的,所以,這里就不過多的說明,細(xì)節(jié)部分,請查看源碼中的注釋。
fs.unwatchFile = function(filename, listener) { //判斷filename是否合法,不合法,則拋出異常 nullCheck(filename); // 把filename轉(zhuǎn)換成絕對地址 filename = pathModule.resolve(filename); // 判斷需要解除綁定文件,是否有緩存StatWatchers的實(shí)例, // 如果沒有,則表示,沒有綁定過監(jiān)聽事件,則不需要去解除綁定 if (!inStatWatchers(filename)) return; var stat = statWatchers[filename]; // 依然覺得,上兩行代碼,是可以優(yōu)化一下的,如下: // var stat = inStatWatchers(filename); //if(!stat){return "";} //依然是兩行代碼,可是卻少了一次作用鏈的查找,和遍歷對象的取值 // 判斷,第二個(gè)參數(shù),是否為一個(gè)function,如果是,則移除該function的回調(diào) // 否則,移除該文件所有的監(jiān)聽回調(diào)函數(shù) if (util.isFunction(listener)) { stat.removeListener('change', listener); } else { stat.removeAllListeners('change'); } // 判斷該文件,是否還有監(jiān)聽的回調(diào)函數(shù),如果沒有了,則清除 // listenerCount方法,是繼承自EventEmitter的原型鏈中的方法ßßß if (EventEmitter.listenerCount(stat, 'change') === 0) { stat.stop(); statWatchers[filename] = undefined; } };
看到這里,想必您也會(huì)想到一個(gè)問題吧,如果我要監(jiān)聽的文件很多,不是要給所有的文件都綁定這個(gè)事件,而只要其中一個(gè)文件出現(xiàn)了問題,就會(huì)導(dǎo)致整個(gè)程序崩潰,這樣的話,維護(hù)成本也太高了吧?
所以說呢,Nodejs的開發(fā)者們,也不會(huì)做這么為難自己的事情不是,它們提供了一個(gè)監(jiān)聽目錄的方法,即fs.watch方法。接下來,就看下這個(gè)驚人的watch的方法,是如何使用以及實(shí)現(xiàn)的吧。
fs.watch方法
該方法是用于監(jiān)聽指定文件或者目錄是否修改的方法,其使用方法為:
fs.watch(filename,[option],listener);
其中:
1:filename:必須,需要被監(jiān)聽的文件的完整路徑的目錄或者文件名
2:option:可選,option支持兩個(gè)參數(shù),persistent屬性和recursive屬性:
- recursive屬性用于沒有找到它具體完成的是哪個(gè)功能,是在源碼中看到有設(shè)置該屬性的,默認(rèn)值為false,在中文文檔:Node.js API 中文版,也沒有找到對應(yīng)的解釋,估計(jì)只有去翻看C++的源碼,才能了解到這些了吧。
- persistent屬性,用于指定了,當(dāng)指定了被監(jiān)視的文件后,是否停止當(dāng)前正在運(yùn)行的應(yīng)用程序,默認(rèn)為true
3:listener:必須,被監(jiān)聽文件發(fā)生改變時(shí)調(diào)用的回調(diào)函數(shù)
回調(diào)函數(shù)傳入兩個(gè)參數(shù)callback(event,filename),其中event取值為“rename”(目錄下有文件被重命名)和“change”(目錄下有文件內(nèi)容被更改)。
看下一個(gè)示例:
var fs = require("fs"); var f = fs.watch("./",function(event,filename){ console.log("event="+event); console.log("filename="+filename); });
這個(gè)示例,不知道您是否會(huì)運(yùn)行一下,我這里測試本地的,發(fā)現(xiàn)一個(gè)問題,就是不管在什么時(shí)候,event的值都是rename,根本就沒有change的時(shí)候,這也可以說明一個(gè)問題,確實(shí)如Node.js API 中文版中所說的一樣,這幾種方法,確實(shí)是不穩(wěn)定的,所以,還是謹(jǐn)慎使用,當(dāng)然,我們還是要看下源碼中的實(shí)現(xiàn)的,因?yàn)檫@是在學(xué)習(xí)~
fs.watch源碼
watch方法的源碼中的邏輯,和watchFile方法的源碼邏輯基本相同,只是繼承的構(gòu)造函數(shù)不同而已。下面就看下源碼的實(shí)現(xiàn)吧。
// watch方法使用到的構(gòu)造函數(shù) function FSWatcher() { // 繼承事件模塊中的實(shí)例內(nèi)部屬性和方法 EventEmitter.call(this); // 緩存this對象,在閉包的回調(diào)函數(shù)中使用 var self = this; // 獲取C++中實(shí)現(xiàn)的FSEvent構(gòu)造函數(shù), // 該獲取是否應(yīng)該放到函數(shù)外部去,優(yōu)化代碼 // 就像在StatWatcher構(gòu)造函數(shù)內(nèi)部的binding.StatWatcher();方法 var FSEvent = process.binding('fs_event_wrap').FSEvent; this._handle = new FSEvent(); this._handle.owner = this; //綁定回調(diào),onchange事件 this._handle.onchange = function(status, event, filename) { // event變了好像是有問題的,我本地測試,event的值一直是“rename” // 根據(jù)status的值,作出不同的處理 if (status < 0) { self._handle.close(); self.emit('error', errnoException(status, 'watch')); } else { self.emit('change', event, filename); } }; } // FSWatcher的原型鏈繼承EventEmitter構(gòu)造函數(shù)的原型鏈的屬性和方法 util.inherits(FSWatcher, EventEmitter); // start方法,當(dāng)初始化構(gòu)造函數(shù)之后,要執(zhí)行該方法,才能開始監(jiān)聽filename指向的目錄或者文件 FSWatcher.prototype.start = function(filename, persistent, recursive) { nullCheck(filename); //調(diào)用C++中實(shí)現(xiàn)的方法,開始執(zhí)行監(jiān)聽動(dòng)作 var err = this._handle.start(pathModule._makeLong(filename), persistent, recursive); // 如果監(jiān)聽時(shí),沒有能正確的執(zhí)行,則關(guān)閉該實(shí)例,并且拋出一個(gè)異常 if (err) { this._handle.close(); throw errnoException(err, 'watch'); } }; // 關(guān)閉監(jiān)聽 FSWatcher.prototype.close = function() { this._handle.close(); }; fs.watch = function(filename) { // 判斷filename是否合法 nullCheck(filename); var watcher; var options; var listener; // 判斷是否有參數(shù) // 初始化參數(shù)和回調(diào)函數(shù) if (util.isObject(arguments[1])) { options = arguments[1]; listener = arguments[2]; } else { options = {}; listener = arguments[1]; } // 給persistent和recursive設(shè)置默認(rèn)值,這里我依然覺得是可以優(yōu)化的。 // 既然在后面只是使用persistent和recursive,那么為何不定義著涼變量 // var persistent = options.persistent, // recursive = options.recursive; // if(util.isUndefined(persistent)) persistent = true; // if(util.isUndefined(recursive)) recursive = false; // ... // watcher.start(filename,persistent,recursive); // 我會(huì)認(rèn)為,去一個(gè)對象中查找變量,比直接查找到一個(gè)變量,要花費(fèi)多一點(diǎn)點(diǎn)的時(shí)間。 if (util.isUndefined(options.persistent)) options.persistent = true; if (util.isUndefined(options.recursive)) options.recursive = false; // 創(chuàng)建FSWatcher的實(shí)例,并執(zhí)行實(shí)例中的start方法,開始監(jiān)聽filename的更新事件 watcher = new FSWatcher(); watcher.start(filename, options.persistent, options.recursive); // 如果有回調(diào)函數(shù),則添加一個(gè)綁定事件,并設(shè)置它的回調(diào)函數(shù) if (listener) { watcher.addListener('change', listener); } // 返回該實(shí)例 return watcher; };
到這里,基本上,監(jiān)聽目錄和文件相關(guān)的API就說完來,這里繼續(xù)一些補(bǔ)充信息,是之前并沒有說到的,首先,watchFile方法的關(guān)閉,以及再次綁定事件等,看下面的示例吧。
var fs = require("fs"); var f = fs.watch("./",function(event,filename){ console.log("event="+event); console.log("filename="+filename); }); f.on("change",function(event,filename){ console.log("change12"); f.close(); //關(guān)閉 }); var ff = fs.watchFile("./message.txt",function(curr,prev){ console.log("change21"); }); ff.on("change",function(){ console.log("change22"); ff.stop(); //關(guān)閉 });
因?yàn)樵趙atch和watchFile使用時(shí),都是返回的它們使用的構(gòu)造函數(shù)的實(shí)例,所以,我們自己也可以根據(jù)這個(gè)實(shí)例,進(jìn)行一些擴(kuò)展,而且,這個(gè)實(shí)例,是包含整個(gè)event模塊的所有的方法的,所以,可以直接綁定一些自定義事件,甚至直接觸發(fā)一些自定義事件,比如,再看下面的代碼:
var fs = require("fs"); var f = fs.watch("./",function(event,filename){ console.log("change11"); }); var ff = fs.watchFile("./message.txt",function(curr,prev){ console.log("change21"); }); f.emit("change"); ff.emit("change");
基本上,這個(gè)實(shí)例,就是一個(gè)EventEmitter的實(shí)例。OK,這個(gè)說到這里,就基本上結(jié)束了。
總結(jié)
注:本文將到的watchFile,watch等方法,都是屬于不穩(wěn)定的方法,在有些平臺下,或者一些系統(tǒng)的設(shè)置下,可能出現(xiàn)獲取不到準(zhǔn)確值的情況,所以謹(jǐn)慎使用,這個(gè)如果可以,應(yīng)該去花點(diǎn)時(shí)間,研究下grunt中,是如何監(jiān)聽文件變化的,進(jìn)而補(bǔ)充本文中沒有實(shí)現(xiàn)的一些功能(不穩(wěn)定)。
關(guān)于Nodejs的fs模塊的內(nèi)容,到這里就結(jié)束了,接下來就是TCP和UDP的數(shù)據(jù)通信相關(guān)的內(nèi)容了,也是創(chuàng)建服務(wù)器的相關(guān)內(nèi)容,本模塊的周期過長,中間工作有點(diǎn)招架不住,一直沒有調(diào)節(jié)好,一直處于比較疲憊的狀態(tài)下,中間的間隔竟然達(dá)到三個(gè)月之久,希望以后不會(huì)再這樣來。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Node.js使用多進(jìn)程提高任務(wù)執(zhí)行效率
在Node.JS中使用多進(jìn)程非常簡單,合理使用多進(jìn)程,可以解放硬件的能力,讓軟件的運(yùn)行效率得到肉眼可見的提升。本文詳細(xì)講解了Node.js使用多進(jìn)程提高任務(wù)執(zhí)行效率的方法,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09使用node.js半年來總結(jié)的 10 條經(jīng)驗(yàn)
從3月初來到帝都某創(chuàng)業(yè)公司的服務(wù)器團(tuán)隊(duì)實(shí)習(xí),到現(xiàn)在已接近半年的時(shí)間。PS: 已轉(zhuǎn)正,服務(wù)器端用的 Node。2014-08-08nodejs對express中next函數(shù)的一些理解
這篇文章主要介紹了nodejs對express中next函數(shù)的一些理解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-09-09node實(shí)現(xiàn)socket鏈接與GPRS進(jìn)行通信的方法
這篇文章主要介紹了node實(shí)現(xiàn)socket鏈接與GPRS進(jìn)行通信的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05node.js中的http.response.write方法使用說明
這篇文章主要介紹了node.js中的http.response.write方法使用說明,本文介紹了http.response.write的方法說明、語法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12node.js的http.createServer過程深入解析
這篇文章主要給大家介紹了關(guān)于node.js的http.createServer過程的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用node.js具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06實(shí)例分析nodejs模塊xml2js解析xml過程中遇到的坑
這篇文章主要介紹了實(shí)例分析nodejs模塊xml2js解析xml過程中遇到的坑,涉及nodejs模塊xml2js解析xml過程中parseString方法參數(shù)使用技巧,需要的朋友可以參考下2017-03-03Windows系統(tǒng)下使用Sublime搭建nodejs環(huán)境
最近在研究Nodejs開發(fā),俗話說,工欲善其事,必先利其器,當(dāng)然要找到一款用著順手的編輯器作為開始。這里我們選擇的是Sublime Text 3,除了漂亮的用戶界面,最吸引我的就是它的插件擴(kuò)展功能以及跨平臺特性。2015-04-04