之前一直以傳統(tǒng)后端的思維來寫nodejs的代碼,發(fā)現(xiàn)運(yùn)行結(jié)果與我的同步思維方式不太一樣,所以需要全面將nodejs學(xué)習(xí)一下。此學(xué)習(xí)筆記適合后端同學(xué)學(xué)習(xí)nodejs的時候觀看,前端大佬可以多多指正。
console.log(setTimeout);
console.log(setInterval);
console.log(setImmediate);
console.log(__filename); // 當(dāng)前文件的全名
console.log(__dirname); //
console.log(process); // 進(jìn)程信息,全局變量
process就是當(dāng)前運(yùn)行環(huán)境變量的集合體。例如process.argv就是獲取用戶輸入的參數(shù)
與Java一樣,叫Math
Math.random(); // 返回0~1的浮點(diǎn)數(shù)
需要解決的問題:
腳本變多時,需要手動管理加載順序
不同腳本之間邏輯調(diào)用,需要通過全局變量的方式去交流,例如:JQUERY。將輸出放到全局變量中,然后由其他部分進(jìn)行使用
沒有html怎么辦?
nodejs中使用CommonJs模塊規(guī)范,加載另一個js,用require函數(shù)來獲取即可。
// demo.js
console.log("-----------");
let lib = require('./lib');
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
可以看見,模塊中定義模塊輸出的方式:默認(rèn)會注入一個叫export的變量,在該變量上掛參數(shù)就相當(dāng)于給當(dāng)前被require對象里面附一個值。還可以掛函數(shù),對象等,理論上就是在輸出對象中加對象。所以在exports中我們可以掛各種類型的結(jié)構(gòu)
同時,對于exports來說,外面可以改變模塊里面的內(nèi)容,是同一個引用。
// demo.js
console.log("-----------");
let lib = require('./lib');
lib.addd = '*******************';
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
setTimeout(()=>{
console.log(exports)
},2000);
運(yùn)行結(jié)果如下,可以看見修改了外面被require的對象,里面的exports對象也被修改了
特定地,如果希望被require出來的不是一個對象,而是一個方法,或者變量啥的,可以使用module.exports,但是會覆蓋掉之前懟exports變量的修改。
// demo.js
console.log("-----------");
let lib = require('./lib');
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
module.exports = function dsa() {
return '123'
};
最終打印的結(jié)果為
// demo.js
console.log("-----------");
let lib = require('./lib');
lib.addd = '*******************';
console.log('---------',lib);
// lib.js
console.log('==========');
exports.hello = '++++++++++';
exports.word = '///////////////';
exports.add = function () {
console.log('1111111111111')
};
setTimeout(()=>{
console.log(exports)
},2000);
module.exports = function dsa() {
return '123'
};
setTimeout(()=>{
console.log(module.exports)
},2000);
運(yùn)行結(jié)果為:
process.stdin.on('data', (e) => {
const x = e.toString().trim();
console.log(x);
} );
每個語言都有包管理工具,不過nodejs有個坑,就是npm有時候版本和nodejs不匹配,這個時候就會拋出一些莫名其妙的錯誤。碰到這種情況,就只能去npm官網(wǎng)解決問題部分尋找結(jié)果了。
要使用npm,需要本身就是一個npm目錄,所以需要使用 npm init 來聲明為npm 包
dependencies:放在里面,npm install時會被自動下載,聲明當(dāng)前npm包所有的依賴
npm install xxx
npm uninstall xxx
npm是國外的鏡像,可以使用淘寶的npm鏡像,可以去NPM鏡像查看相關(guān)的方法
值得注意的是,用cnpm的時候要加上--save指令,否則dependencies中不會加進(jìn)去
很多同學(xué)不知道自己適合用什么包,比如我想連接redis,該使用什么包呢?就可以使用 npm search redis來尋找了,相同的,docker search redis/composer search redis 等等都是這么玩的。
基于V8運(yùn)行環(huán)境
事件驅(qū)動:非阻塞式的IO模型
nodejs官方網(wǎng)站文檔頁面 nodejs官方網(wǎng)站文檔中文頁面
以os為例,在源碼的lib文件中:internalBinding('os') 在 src/node_os.cc中再調(diào)用v8的能力
EventEmitter,process繼承與它,所以可以往上拋事件,也就是典型的觀察者模式。底層的能力封裝起來放到一個模塊中,外面的模塊拿到這個代碼,通過事件的監(jiān)聽器,就能比較方便的,知道子模塊里面發(fā)生的變化。
觀察者模式,可以用來解決兩個對象的交流問題。
其實(shí)這個方法也可以實(shí)現(xiàn)兩個函數(shù)的先后執(zhí)行,從而將代碼過程化,我看到這個還是比較興奮的,這樣我就可以解決本來具有先后執(zhí)行順序的代碼,由于nodejs的異步特性導(dǎo)致無法實(shí)現(xiàn)的,可以利用這個模式實(shí)現(xiàn)
const EventEmitter = require('events').EventEmitter;
class X extends EventEmitter{
constructor(){
super();
setInterval(()=>{
this.emit('newlesson',{
price:Math.random()*100
});
},3000)
}
}
const x = new X();
x.addListener('newlesson',(res)=>{
console.log('buy!',res);
});
本文由博客群發(fā)一文多發(fā)等運(yùn)營工具平臺 OpenWrite 發(fā)布
聯(lián)系客服