之前一直以传统后端的思维来写nodejs的代码,发现运行结果与我的同步思维方式不太一样,所以需要全面将nodejs学习一下。此学习笔记适合后端同学学习nodejs的时候观看,前端大佬可以多多指正。
process就是当前运行环境变量的集合体。例如process.argv就是获取用户输入的参数
与Java一样,叫Math
Math.random(); // 返回0~1的浮点数需要解决的问题:
脚本变多时,需要手动管理加载顺序 不同脚本之间逻辑调用,需要通过全局变量的方式去交流,例如:JQUERY。将输出放到全局变量中,然后由其他部分进行使用 没有html怎么办?
nodejs中使用CommonJs模块规范,加载另一个js,用require函数来获取即可。
// 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') };可以看见,模块中定义模块输出的方式:默认会注入一个叫export的变量,在该变量上挂参数就相当于给当前被require对象里面附一个值。还可以挂函数,对象等,理论上就是在输出对象中加对象。所以在exports中我们可以挂各种类型的结构 同时,对于exports来说,外面可以改变模块里面的内容,是同一个引用。
// 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);运行结果如下,可以看见修改了外面被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' };最终打印的结果为 可以看到结果中exports变量的值并没有被输出出来,得到这样的结果有两种可能性,第一是module.exports将exports对象给覆盖掉了,第二种是module.exports和exports在文件被require的时候其实是两个不同的东西,指向两个不同的内存,当模块被require的时候,如果module.exports没有被指定,那么就require出来的是exports对象,如果module.exports被指定了,那么就使用module,exports。我比较倾向于后面这种解释,下面来证实我的观点。
// 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);运行结果为: 可以看到,在demo.js中给引用的lib新增了addd属性,最终是作用到了module.exports上,同时,exports打印的结果与module.exports并不一样,说明,module.exports和exports不是一个对象,只是在一个模块被引用时,module.exports的优先级要高于exports。
每个语言都有包管理工具,不过nodejs有个坑,就是npm有时候版本和nodejs不匹配,这个时候就会抛出一些莫名其妙的错误。碰到这种情况,就只能去npm官网解决问题部分寻找结果了。
要使用npm,需要本身就是一个npm目录,所以需要使用 npm init 来声明为npm 包
dependencies:放在里面,npm install时会被自动下载,声明当前npm包所有的依赖
npm是国外的镜像,可以使用淘宝的npm镜像,可以去NPM镜像查看相关的方法 值得注意的是,用cnpm的时候要加上--save指令,否则dependencies中不会加进去
很多同学不知道自己适合用什么包,比如我想连接redis,该使用什么包呢?就可以使用 npm search redis来寻找了,相同的,docker search redis/composer search redis 等等都是这么玩的。
基于V8运行环境 事件驱动:非阻塞式的IO模型
nodejs官方网站文档页面 nodejs官方网站文档中文页面
以os为例,在源码的lib文件中:internalBinding('os') 在 src/node_os.cc中再调用v8的能力
EventEmitter,process继承与它,所以可以往上抛事件,也就是典型的观察者模式。底层的能力封装起来放到一个模块中,外面的模块拿到这个代码,通过事件的监听器,就能比较方便的,知道子模块里面发生的变化。 观察者模式,可以用来解决两个对象的交流问题。 其实这个方法也可以实现两个函数的先后执行,从而将代码过程化,我看到这个还是比较兴奋的,这样我就可以解决本来具有先后执行顺序的代码,由于nodejs的异步特性导致无法实现的,可以利用这个模式实现
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); });炒鸡辣鸡原创文章,转载请注明来源
