zoukankan      html  css  js  c++  java
  • java程序员的NodeJS初识篇

    摘要

    作为一个一直用java来写后端的程序员用NodeJS来写后台,实在不是很爽。这里记下这两个月的NodeJS学习所遇之坑,与java转NodeJS的同仁共勉。学习时间不长,若有理解错误,望指正。

    一.JS基本

    exports,module.exports

    • exports 就是module.exports的引用
    • 在module 被计算之前,会将module.exports的值赋给exports
    • 当module.exports赋值之后,再对exports改值,不会影响module.exports的值,而外部
      require module的时候,如果module.exports有定义,调用的是module.exports的值。
      eg1.
    module.exports.hello = true; // Exported from require of module
    exports = { hello: false };  // Not exported, only available in the module

    eg2.
    module.js

    module.exports = 'a';
    exports.B = 'b';

    call.js

    var module = require('module');
    console.log(module.B);
    //undefined
    • exports 就是传统的module实例,可以exports 变量,也可以exports 方法,调用的时候都一样,通过
      instance.xxx来调用

    eg. module.js

    exports.A = 'a'
    exports.add = function add(a, b){
      return a+b;
    }

    call.js

    var module = require('module');
    module.A;
    module.add(xx,xx);
    • module.exports可以将module,exports成任何合法的js 类型,boolean,JSON,function都可以。
      从这点上说,就不能将javascript中的module类比成java中的类/实例。
    module.exports = function (a, b) {
      return a + b;
    }

    import 某个module的属性

    与直接import不同
    import { test } from ‘xxx’
    issue

    class 与instance

    js中并没有class,一切皆为对象。面向对象的实现是通过prototype来实现的。
    例如一般在某个文件中调用某个js文件,就是在文件开始部分require,然后在文件中
    各处引用。而这点与java不同,java是首先import,然后具体用的时候需要new 一个instance再使用

    js中require 以后直接使用。不需要new instance。所以各处用的都是同一个instance。
    如果想new一个object,创建新的instance,则需要使用原型。这样每个new出来的对象就有对应的
    原型方法了。
    eg.
    test.js

    // 类似于构造函数
    function Test() {
    
    }
    
    Test.prototype.add = function (a,b) {
      return a+b;
    };
    module.exports = Test;

    call.js

    require Test from 'test';
    function sub(){
    var test1 = new Test();
    test1.add();
    }

    作用域

    对于方法而言,js没有类似于java的那么强的域控制public,protected,private
    就分内部与外部,只在函数内部使用的就不要export出去。

    二.异步回调

    js 代码写起来和java代码最大的不同就是回调了。
    java代码基本消灭了随意跳转的goto。阅读代码块或者写代码块时基本就是按照从上
    到下的顺序即可。因为java代码都是同步执行的。而JS很多都是异步执行,所以如果你想
    你的逻辑是顺序执行的话,必须等待异步执行返回结果后,再去执行下面的代码。因为js
    方法大多是非阻塞。

    —-2017.3.14更新———-
    其实这代表了两种不同的并发处理方式,一种是java的,基于线程的并发,一个task一个线程。
    写起来也是顺序执行的。但是task增多,多个线程之间切换代价昂贵,可能会导致吞吐量下降。

    而nodejs,则是基于事件的并发,单线程处理事件,每个并发流实现为一个有限状态机。所以需要回调。应用直接控制。但是当并发负载增加的时候,吞吐量饱和响应时间线性增长

    还有一种的话就是之前介绍的cassandra实现的SEDA模型

    eg.实现查mongo数据库
    java code

    MongoClient  client = new MongoClient(url);
    Collection coll = client.getCollection('test');
    ResultSet<String> rs = coll.find({});

    而js则是

    MongoClient.connect(url, function(err, db) {
      //回调,等待连接成功,才能执行下一步。
      if (err) {
        callback(err);
      }
      var coll = db.collection('test');
      coll.find({name:"mike"}).toArray(function(err, results) {
          console.log(results);
        db.close();
      });
    });

    三.内存溢出

    NodeJs使用google V8来管理内存,V8会将js代码编译为本地代码,然后执行它。
    V8会按需进行内存的分配和释放。和JVM差不多了。将内存区域分区,

    • 代码区域

    • 值类型的数据,内部变量,控制程序的指针。

    • 保存引用类型(对象,字符串,闭包)

    在做mongodb数据大量插入的时候遇到过一次内存溢出的问题,所以需要分析溢出原因,
    java中一般是dump处文件,然后用其他工具分析对象。NodeJs也类似。

    var heapdump = require('heapdump');
    heapdump.writeSnapshot();

    然后在chrome中的Profile工具来分析溢出对象。但是实际中此效果不好,原因是chrome的内存不够大(可能需要调整浏览器内存大小),另外结果不是很直观。还可以使用util包中输出内存占用

    var util = require('util');
    console.log(util.inspect(process.memoryUsage()));

    内存溢出原因:
    在上面提到过在js中基本都是回调函数,mongo插入同样也是。使用mongo.insertMany(array)来批量插入提高性能。同时充分利用异步特点,使用async.each来控制,模拟多线程并发。但是这边就存在一个问题,有经验的老手就能看出来了,插入的数据array占用的内存什么时候释放。mongo.insertMany调用开始,到真正插入到db中需要一定时间。插入上千万条数据的,内存回收不及时的话肯定是要溢出的。所以要加一层并发控制,比如说以10万条数据为内层并发,这些数据的插入是并发操作的,无序的,等这一批数据插入成功后,再进行下一批数据插入,释放内存。

    四.打包

    java中依赖其他包,使用jar包。build工具可以用maven,gradle。
    nodejs中依赖其他包,使用module.使用npm来构建
    在package.json中的 files属性中定义要打包的文件
    “files”: [
    “src/publish”,
    ],

    在main属性中定义main文件
    “main”: “src/index.js”,

    使用npm publish命令到repository。如果是本地的调用,使用npm pack 打包
    在其他project中使用 npm install -s $PATH/publish-service-0.0.1.tgz添加引用

    五.参考

    http://www.hacksparrow.com/node-js-exports-vs-module-exports.html
    https://cnodejs.org/topic/55accdeab4ab1d7d02bf0d8c
    http://wwsun.github.io/posts/understanding-nodejs-gc.html

  • 相关阅读:
    关于IIS7发布网站
    二叉树遍历逆向
    山药熬粥补脾
    山萸肉补肝阴
    生黄芪痔疮
    酸石榴
    生石膏粉清实热
    熟地黄被肾阴
    龙眼肉(桂圆肉)
    鸡内金消食导滞
  • 原文地址:https://www.cnblogs.com/stoneFang/p/6715270.html
Copyright © 2011-2022 走看看