,以传统后端开发者的视角学习异步Nodejs。之前一直在用传统后端思维写nodejs代码,发现运行结果和我同步的思维方式不太一样,需要全面学习nodejs。这篇学习笔记适合后端同学在学习nodejs的时候看,前端大佬多多指正。环境变量console.log(setTimeout);console.log(setInterval);console.log(setImmediate);console.log(__filename);//当前文件全名console.log(__dirname);//控制台日志(进程);//进程信息,全局变量process是当前运行环境变量的集合。比如process.argv就是获取用户输入的参数。数学库和Java一样,叫做MathMath.random();//返回0~1浮点数的模块规范的exports和module.exports的关系,需要手动管理加载顺序不同脚本之间的逻辑调用,需要通过全局变量进行通信,例如:JQUERY。将输出放在一个全局变量中,然后供其他部分使用如果没有html怎么办?使用nodejs中的CommonJs模块规范,再加载一个js,使用require函数获取。//demo.jsconsole.log("------------");letlib=require('./lib');console.log('--------',lib);//lib.jsconsole.log('==========');exports.hello='++++++++++';exports.word='//////////////';exports.add=function(){console.log('1111111111111')};可以看到,模块定义模块输出的方式:默认情况下,它会注入一个叫做exportvariable的函数,给这个变量附加一个参数就相当于给当前需要的对象附加一个值。也可以挂函数,对象等,理论上,给输出对象添加对象。所以在出口中,我们可以挂各种类型的结构。同时,对于导出,模块里面的内容可以在外面改,这是同一个引用。//demo.jsconsole.log("------------");letlib=require('./lib');lib.addd='*******************';console.log('--------',lib);//lib.jsconsole.log('==========');exports.hello='++++++++++';exports.word='////////////////';exports.add=function(){console.log('1111111111111')};setTimeout(()=>{console.log(exports)},2000);运行结果如下,可以看到外面的required对象被修改了,里面的exports对象也被修改了。具体来说,如果你想要require的不是一个对象,而是一个方法,或者一个变量,你可以使用module.exports,但是它会覆盖之前对exports变量的修改。//demo.jsconsole.log("------------");letlib=require('./lib');console.log('--------',lib);//lib.jsconsole.log('==========');exports.hello='++++++++++';exports.word='///////////////';exports.add=function(){console.log('1111111111111')};module.exports=functiondsa(){return'123'};最后打印出来的结果是可以看到结果中exports变量的值还没有输出。有两种可能得到这样的结果。第一是module.exports覆盖了exports对象,第二是module.exports和Exports在需要文件的时候其实是两个不同的东西,指向两个不同的内存。当需要模块时,如果没有指定module.exports,那么需要的对象就是exports对象。如果指定了module.exports,则使用module,exports。我更倾向于后一种解释,下面将印证我的观点。//demo.jsconsole.log("------------");letlib=require('./lib');lib.addd='*******************';console.log('--------',lib);//lib.jsconsole.log('==========');exports.hello='++++++++++';exports.word='////////////////';exports.add=function(){console.log('1111111111111')};setTimeout(()=>{console.log(exports)},2000);module.exports=functiondsa(){return'123'};setTimeout(()=>{console.log(module.exports)},2000);运行结果为:可以看到在demo.js中引用的lib中添加了addd属性,最后应用到module.exports中。同时,exports打印的结果与module.exports不同,意味着module.exports和exports不是一个对象,但是当引用一个模块时,module.exports的优先级高于exports。获取控制台输入(标准输入和输出)process.stdin.on('data',(e)=>{constx=e.toString().trim();console.log(x);});包管理工具每种语言都有包管理工具,但是nodejs有个坑,就是有时候npm的版本和nodejs不匹配,这时候会抛出一些莫名其妙的错误。这种情况只能去npm官网的问题解决栏目找结果。使用npm,npminit本身需要是一个npm目录,所以需要使用npminit声明为一个npm包package.jsondependencies:放入,npminstall时会自动下载,并声明所有的依赖当前npm包的安装和卸载npminstallxxxnpmuninstallxxx国内镜像npm是国外镜像,可以使用淘宝的npm镜像,可以去npm镜像查看相关方法值得注意的是,使用cnpm时,必须加上--save命令,否则不会添加到依赖项中npmsearchxxx很多同学不知道自己适合什么包。比如我要连接redis,应该用什么包?你可以使用npmsearchredis来找到它。同样的,dockersearchredis/composersearchredis等等都是这样玩的。nodejs架构基于V8运行环境事件驱动:非阻塞IO模型内置模块nodejs官网文档页面nodejs官网文档中文页面底层能力如何完成以os为例,在lib文件中源码:internalBinding('os')在src/node_os.cc中,调用v8能力Event模块实现观察者模式,然后让两个对象传递EventEmitter,进程继承,所以事件可以被向上抛出,这是典型的观察者模式。将底层能力封装放在一个模块中,外部模块获取这段代码,通过事件监听器,更方便的获知子模块发生的变化。观察者模式可以用来解决两个对象之间的通信问题。其实这种方法也可以实现两个函数的顺序执行,从而实现代码的程序化。看到这里我还是蛮兴奋的,这样我就可以解决原本有顺序执行顺序的代码,由于nodejs的异步特性无法实现,可以用这种方式实现constEventEmitter=require('events').EventEmitter;X类扩展EventEmitter{constructor(){super();setInterval(()=>{this.emit('newlesson',{price:Math.random()*100});},3000)}}constx=newX();x.addListener('newlesson',(res)=>{console.log('buy!',res);});炸鸡麻辣鸡原创文章,转载请注明出处
