文档章节

nodejs插件的学习笔记

前端届的科比
 前端届的科比
发布于 2014/06/16 17:30
字数 4201
阅读 173
收藏 0
点赞 0
评论 0

###async

并发连接数控制。

mapLimit(arr, limit, iterator, callback)接口, callback是每次调用iterator第二个参数,必须调用一下,不然只会执行到limit的次数,而不是arr.length的次数,callback执行时的第2个参数就是每次iterator调用时传入参数的数组,使用示例:

async.mapLimit(urls, 5, function (url, callback) {
  //fetchUrl(url, callback);
  callback(null, 'this arg is result, url: '+ url);
}, function (err, result) {
  console.log('final:');
  console.log(result);
});

bcrypt

加盐用法

  // 加密算法的强度,默认为10
  var SALT_FACTOR = 10;
  bcrypt.genSalt(SALT_FACTOR, function(err, salt){
    if(err){
      return next(err);
    }
    bcrypt.hash(user.password, salt, function(err, hash){
      if(err){
        return next(err);
      }
      user.password = hash;
      next(null);
    });
  });

对比密码方法

  bcrypt.compare(password, this.password, function(err, isMatch){
    if(err){
      return cb(err);
    }
    cb(null, isMatch);
  });

###benchmark

基准测试。http://jsperf.com/

可以分享benchmark。

npm安装:npm i --save benchmark

使用示例:

var Benchmark = require('benchmark');
var suite = new Benchmark.Suite;
var number = '100';

// 添加测试
suite
.add('+', function() {
  int1(number);
})
.add('parseInt', function() {
  int2(number);
})
.add('Number', function () {
  int3(number);
})

// 每个测试跑完后,输出信息
.on('cycle', function(event) {
  console.log(String(event.target));
})

.on('complete', function() {
  console.log('Fastest is ' + this.filter('fastest').pluck('name'));
})

// 这里的 async 不是 mocha 测试那个 async 的意思,这个选项与它的时间计算有关,默认勾上就好了。
.run({ 'async': true });

bower

  • bower安装bootstrap:bower install bootstrap

  • bower init生成配置文件bower.json

  • 自定义bower安装目录: 1、在工作目录下新建.bowerrc文件 2、内容为:

    {
      "directory": "public/libs"
    }
    

    这样bower安装Bootstrap、jquery都会在上述目录安装

chai

官网地址:http://chaijs.com/。chai是个断言库,可以导出如should:var should = chai.should();

chai有多种接口选择如:

should

  chai.should();
  foo.should.be.a('string');
  foo.should.equal('bar');
  foo.should.have.length(3);
  tea.should.have.property('flavors')
    .with.length(3);

expect

  var expect = chai.expect;
  expect(foo).to.be.a('string');
  expect(foo).to.equal('bar');
  expect(foo).to.have.length(3);
  expect(tea).to.have.property('flavors')
    .with.length(3);

assert

  var assert = chai.assert;
  assert.typeOf(foo, 'string');
  assert.equal(foo, 'bar');
  assert.lengthOf(foo, 3)
  assert.property(tea, 'flavors');
  assert.lengthOf(tea.flavors, 3);

###cheerio

可以理解为Node.js版的jQuery。使用示例(与superagent结合使用):

superagent.get('https://cnodejs.org')
  .end(function(err, sres){
    if(err){return;}
    var $ = cheerio.load(sres.text);
    var cont = $('.cont').html();
  });

###connect-mongo

中间件。可用作mongodb的会话持久化

var mongoStore = require('connect-mongo')(express);

app.use(express.session({
  secrect: 'imooc',
  store: new mongoStore({
    url: 'mongodb://localhost/imooc',
    collection: 'sessions' // 指定存到mongodb里的collection
  })
}));

###eventproxy

控制并发。

重复异步协作例子:在异步操作中,我们需要在所有异步调用结束后,执行某些操作。

var ep = new EventProxy();
ep.after('got_file', files.length, function(list) {
  // 在所有文件的异步执行结束后将被执行
  // 所有文件的内容都存在list数组中
});

for (var i = 0; i < files.length; i++) {
  fs.readFile(files[i], 'utf-8', function(err, content) {
    // 触发结果事件
    ep.emit('got_file', content);
  });
}

###express

express的表单上传文件

1、引入express中间件处理:app.use(express.multipart); (可能现在这个中间件已抽离出来了) 2、form表单声明指定支持多种文件上传

<form enctype="multipart/form-data">
  <input type="file" name="upload">

3、服务器端用req.files来读取:

var uploadData = req.files.

利用mongodb做会话的持久化

// 先引入connect-mongo,cookie-parser等
// 外面再安装on-headers模块
var cookieParser = require('cookie-parser');
var expressSession = require('express-session');
var mongoStore = require('connect-mongo')(expressSession);

// 引用express.cookieParse
app.use(cookieParse());

// express.session
app.use(expressSession({
  secret: 'imooc',
  saveUninitialized: false, // don't create session until something stored
  resave: false, //don't save session if unmodified
  store: new mongoStore({
    url: 'mongodb://localhost/imooc',
    collection: 'sessions'
  })
}));

// 用法是把数据保存在req.session里
app.get('/', function(req, res){
  req.session.uer = req.body.user;
});

app.get('/admin/userlist', user.signinRequired, user.adminRequired, user.list); 可以直接传递执行方法,然后每个方法通过是否调用next()方法来执行下一个,从而达到验证的效果。如上的执行是:要查看admin的管理者列表,必须先登录,登录的用户必须是管理者,才加载用户的list。权限控制需要用到这点!!

预处理示例:

  // prev handler
  app.use(function(req, res, next){
    // do something ...
    next();
  });

指定静态资源

  app.use(express.static(path.join(__dirname, 'bower_components')));

添加本地变量

app.locals.moment = require('moment');

这样在express使用的jade的模板里也能使用moment了。

gulp

全局安装还需本地安装

安装gulp需要全局安装:npm i -g gulp后,再本地安装一次:npm i gulp --save-dev

具体原因可参考: why-do-we-need-to-install-gulp-globally-and-locally what-is-the-point-of-double-install-in-gulp

总结起来就是:

  • 能控制版本,不然开发时都不知道使用的gulp是哪个版本
  • gulp是有点unusual,开发时需要全局的gulp传递给本地的gulp的权限
  • 如果安装在本地了,那为什么还需安装在全局?是为了在系统路径能找到gulp来运行,可能与上面说的权限传递有关吧

如果不想本地再安装的话,可以使用:npm link gulp,它会立刻把全局的gulp链接过来,但貌似这不是太推荐。

mocha

  • npm i grunt-mocha-test --save-dev安装支持grunt的mocha插件

  • describe描述你要测的主体是什么,it描述具体的case内容。

  • mocha init f2e生成浏览器环境执行的测试原型,结构为:

    .
    ├── index.html
    ├── mocha.css
    ├── mocha.js
    └── tests.js
    
  • .only()方法可让你只运行指定的suite/test case,而.skip()则跳过该suite/test case:

    describe('Array', function(){
      describe.only('#indexOf()', function(){
        //...
      })
    })
    
    describe('Array', function(){
      describe('#indexOf()', function(){
        it.only('should return -1 unless present', function(){
        });
        it('should return the index when present', function(){
        });
      })
    })
    

    可在应用.only的地方应用.skip

  • 指定mocha在命令行测试报告形式:mocha --reporter doc, 更多形式请参考官网。

官网地址:http://mochajs.org/。mocha是一个测试框架,可以让你使用自己喜爱的断言库,如should.js,node自带的_assert_模块,chai,expect.js, better-assert等等。

mocha的接口有BDD, TDD, exports口味的接口,另外也有QUnit, require

BDD

提供 describe(), context(), it(), before(), after(), beforeEach(), afterEach()。

describe('Array#index', function(){
  context('when not present', function(){
    it('should not throw an error', function(){
      (function(){
        [1,2,3].indexOf(4)
      }).should.not.throw()
    })

    it('should return -1', function(){
      [1,2,3].indexOf(4).should.equal(-1)
    })
  })
})

TDD

提供 suite(), test(), suiteSetup(), suiteTeardown(), setup(), teardown()。

suite('Array', function(){
  setup(function(){
    // 初始化执行工作...
  })

  suite('#indexOf()', function(){
    test('should return -1', function(){
      assert.equal(-1, [1,2,3].indexOf(4))
    })
  })
})

exports

特殊属性:before, beforeEach, after, afterEach object值是suites function值是test-cases

module.exports = {
  before: function(){},

  'Array': {
    '#indexOf': {
      'should return -1': function(){
        [1,2,3].indexOf(4).should.equal(-1)
      }
    }
  }
};

QUnit

扁平式写法,使用TDD的 suite() 和 test(), 但也使用BDD的before, beforeEach, after, afterEach.

function ok(expr, msg){
  if(!expr){
    throw new Error(msg)
  }
}

suite('Array')

test('#length', function(){
  var arr = [1,2,3]
  ok(arr.length === 3)
})

Require

var testCase = require('mocha').describe
var pre = require('mocha').before
var assertions = require('mocha').it
var assert = require('assert')

testCase('Array', function(){
  pre(function(){
    // ...
  });

  testCase('#indexOf()', function(){
    assertions('should return -1 when not present', function(){
      assert.equal([1,2,3].indexOf(4), -1);
    });
  });
});

mocha-phantomjs

headless 浏览器 phantomjs,提供一个命令行的前端脚本测试环境,使得脚本文件运行在浏览器环境中。使用示例:

if(window.mochaPhantomJS){mochaPhantomJS.run();}
else{mocha.run();}

然后在命令行中运行:mocha-phantomjs index.html

###mongodb

  • cat.id === joke.category,比较ID值时,由于是ObjectId类型,不能直接比较,cat.id === joke.category, 要用字符串化后的: String(cat.id) === String(joke.category)
  • show tables可以列出当前的数据表
  • db.users.update({"_id": ObjectId("objectidxxxxxx")}, {$set: {role:55}}) 手动更新数据记录
  • 27017是MongoDB实例运行的默认端口
  • 清点数据记录条数:db.movies.find({}).count()
  • 删除所有数据:db.movies.remove()
  • 比起monk,mongoskin更适合与mongodb协作。

使用示例

1、在mongodb文件夹注册工作目录:mongod --dbpath c:\node\nodetest1\data 2、在mongodb文件夹运行mongo,进入mongodb的shell命令行界面:mongo 3、创建数据库:use nodetest1 4、添加数据记录。mongodb使用JSON结构,创建记录时会自动添加_idkey和value:db.usercollection.insert({"username": "testuser1", "email": "testuser1@testdomain.com"}) db指向创建的nodetest1数据库,usercollection为自动创建的collection。 5、查看刚刚的记录:db.usercollection.find().pretty() 6、在js文件的使用:

var mongo = require('mongodb');
var monk = require('monk');
// monk获取数据库
var db = monk('localhost:27017/nodetest1');
// 使router可以访问到db
app.use(function(req, res, next){
  req.db = db;
  next();
});

// 拉去数据库数据
router.get('/userlist', function(req, res){
  var db = req.db;
  var collection = db.get('usercollection');
  collection.find({}, {}, function(e, docs){
    res.render('userlist', {
      'userlist': docs
    });
  });
});

安装方式

  • 与Nodejs并列,安装:brew install mongodb
  • 到官网下载,再解压到指定文件夹,每次通过mongod --dbpath c:\node\nodetest1\datamongo来注册目录和启动服务。

###mongoose

  • 数据库直接更新数据记录语法。update效果是把pv值加1并保存到数据库中

    Movie.update({_id: id}, {$inc: {pv: 1}}, function(err){
      if(err){
        console.log(err);
      }
    });
    
  • mongoose支持正则表达式来筛选数据:

    var query = 'keyword';
    var re = new RegExp(query+'.*', 'i');
    
    Movie.find({
      title: re
    }).exec(function(err, movies){
      //...
    });
    
  • mongoose的双向ref用法: 参考以下两个Schema的结构:

    // 电影分类 - category.schema.js
    // ref首字母大写,指向对应的Model
    {
      movies: [{type: ObjectId, ref: 'Movie'}]
    }
    
    // 电影 - movie.schema.js
    {
      category: {
        type: ObjectId,
        ref: 'Category'
      }
    }
    
  • mongoose.populate方法:

    Comment.find({movie:id})
      // populate方法,从'from'键定义的ref值和筛选的key的值来获得相应的记录
      // 从记录里再获取'name'的数据
      .populate('from', 'name')
      .populate('reply.from reply.to', 'name')
      .populate({
        path: 'movies', // movies为Schema中的一个key
        options: {
          limit: 5,
          skip: skipCount  // skipCount:跳过的数据记录数目,但现在这个功能貌似有问题,可以改为用自己的代码实现
        }
      })
      .exec(function(err, comments){})
    
  • mongoose.set('debug', true);打开debug模式

mongoose包括schema, model, document,即模式、模型、文档三种。定义示例:

// schema
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.types.ObjectId; // 或者Schema.ObjectId
var MovieSchema = new mongoose.Schema({
  doctor: String,
  title: String,
  language: String,
  country: String,
  year: Number,
  summary: String,

  // 数组类型,里面还需定义元素格式
  reply:[{
    type: ObjectId,
    ref: 'User'
  }],

  poster: {
    type: ObjectId, // 系统生成ID类型
    ref: 'Poster' // 引用指向的数据库
  },

  meta: {
    createAt:{
      type: Date,
      default: Date.now() // 这是设置默认值的,不是一个新属性
    }
  }
});

// 全局统一设置,在save之前都会执行的动作
MovieSchema.pre('save', function(next){
  // 判断数据是否是新加的
  if(this.isNew){
    this.meta.createAt = Date.now();
  }

  // 将存储流程走下去
  next();
});


// 增加实例方法,在实例调用的方法
UserSchema.methods = {
  comparePassword: function(password, cb){
    bcrypt.compare(password, this.password, function(err, isMatch){
      if(err){
        return cb(err);
      }
      cb(null, isMatch);
    });
  }
};

// 增加静态方法,在模型调用的方法
MovieSchema.statics = {
  // 获取所有数据记录
  fetch: function(cb){
    return this.find({}).sort('meta.createAt').exec(cb);
  },

  // 通过ID获取
  findById: function(id,cb){
    return this.findOne({_id:id}).exec(cb);
  }
};

module.exports = MovieSchema;

model,数据库模型

var mongoose = require('mongoose');
var MovieSchema = require('./schema/movie');

// 编译生成模型:传入模型名字,数据库模式
var Movie = mongoose.model('Movie', MovieSchema);
module.exports = Movie;

documents, 文档实例化

var Movie = require('./models/movie');
var movie = new Moive({
  title: '机械战警',
  doctor: '帕蒂丽雅',
  year:2010
});

// 保存到数据库
movie.save(function(err){
  if(err){
    return handleError(err);
  }
});

documents, 数据库批量查询

var Moive = require('./models/movie');
app.get('/', function(req, res){
  Movie.find({})
    .exec(function(err, movies){
      // ...
    });
});

documents,数据库单条查询

var Movie = require('./models/movie');
app.get('/', function(req, res){
  Movie.findOne({_id: id})
    .exec(function(err, movie){
      // ...
    });
});

documents, 单条数据删除

Movie.remove({_id: id}, function(err, movie){});

在运行模块中的使用:

// 只引入mongoose, 不用引入mongodb了
var mongoose = require('mongoose');
// 链接数据库
mongoose.connect('mongodb://localhost/imooc');

nodemon

这个库是专门调试时候使用的,它会自动检测 node.js 代码的改动,然后帮你自动重启应用。在调试时可以完全用 nodemon 命令代替 node 命令。安装命令:npm i -g nodemon

###q

promise/deferred模型的实现代表:q。Promise的基本概念:promise只有3种状态,未完成,完成fulfilled,失败rejected,状态的改变只发生一次。

  • promise的获取方法。使用例子:

      var Q = require('q');
      var defer = Q.defer();
      /**
       * 获取初始promise
       * @private
       */
      function getInitialPromise() {
        return defer.promise;
      }
    
  • defer.resolve('info');改变Promise状态为fulfilled;defer.reject('info');改变Promise状态为rejected;defer.notify('info');模拟promise进度

  • promise的then()方法接受3个函数参数,第1个处理fulfilled状态回调,第2个处理rejected,第3个处理progress, 返回值是另一个promise。对于outputPromise,initialPromise的function(success), function(error)都返回字符串将其状态由未完成改为fulfilled,调用的是outputPromise.then它自己的function(success)

    var outputPromise = getInitialPromise().then(function(success) {
      console.log(success);
      return 'success';
    }, function(error) {
      console.log(error);
      return 'error';
    }, function(progress) {
      console.log(progress);
      return 'progress';
    });
    defer.notify('in progress'); //控制台打印in progress
    defer.resolve('resolve'); //控制台打印resolve
    defer.reject('reject'); //没有输出。promise的状态只能改变一次
    
  • 当initialPromise的function(fulfilled)或function(rejected)抛出异常时,outputPromise的状态变为rejected

      var outputPromise = getInputPromise().then(function(fulfilled){
        throw new Error('fulfilled');
      },function(rejected){
        throw new Error('rejected');
      });
      outputPromise.then(function(fulfilled){
        console.log('fulfilled: ' + fulfilled);
      },function(rejected){
        console.log('rejected: ' + rejected);
      });
    
      defer.reject();     //控制台打印 rejected [Error:rejected]
      //defer.resolve(); //控制台打印 rejected [Error:fulfilled]
    
  • 当initialPromise的function(fulfilled)或function(rejected)返回promise,outputPromise就会成为这个新的promise.示例:

      var outputPromise = getInputPromise().then(function(fulfilled){
        var myDefer = Q.defer();
        fs.readFile('test.txt','utf8',function(err,data){
            if(!err && data) {
                myDefer.resolve(data);
            }
        });
    
        return myDefer.promise;
      },function(rejected){
        throw new Error('rejected');
      });
    
      outputPromise.then(function(fulfilled){
        console.log(fulfilled);
      },function(rejected){
        console.log(rejected);
      });
    
      defer.resolve(); //控制台打印出 test.txt 的内容
      //defer.reject();
    
  • 当initialPromise没设置fulfilled或rejected的回调时,会传递到outputPromise,调用其fulfilled/rejected的回调

  • 可以使用fail(function(error))来专门针对错误处理,而不是使用then(null,function(error))。

      var outputPromise = getInputPromise().then(function(fulfilled){
        return fulfilled;
      }).fail(function(error){
        console.log('fail: ' + error);
      });
    
  • 可以使用progress(function(progress))来专门针对进度信息进行处理,而不是使用 then(function(success){},function(error){},function(progress){})。

顺序执行,链式调用:由于.then()函数返回的是promise,故可以使用链式的then方法。但注意,这种用法是顺序执行,上一个Promise完成后才执行下一个,不是并行的。使用示例:

var Q = require('q');
var defer = Q.defer();

//promise链
defer.promise.then(function(username){
  return getUser(username);
}).then(function(user){
  console.log(user);
});

defer.resolve('andrew');

// 另外,利用Q也可直接链式调用:
function foo(result){
  return result+result;
}

// 手动连接
Q('hello').then(foo).then(foo).then(foo);

// 动态链接
var funcs = [foo,foo,foo];
funcs.reduce(function(prev, current){
  return prev.then(current);
}, Q('hello'));

并列执行:Q.all([promise1,promise2...])将多个promise组合成一个promise返回。注意:

1、当all里面所有的promise都fulfill时,Q.all返回的promise状态变成fulfill 2、当任意一个promise被reject时,Q.all返回的promise状态立即变成reject

现在知道Q.all会在任意一个promise进入reject状态后立即进入reject状态。如果我们需要等到所有的promise都发生状态后(有的fulfil, 有的reject),再转换Q.all的状态, 这时我们可以使用Q.allSettled

var Q = require('q');
var fs = require('fs');

function printFileContent(fileName) {
  //Todo: 这段代码不够简洁。可以使用Q.denodeify来简化
  var defer = Q.defer();
  fs.readFile(fileName, 'utf8', function(err, data) {
    if (!err && data) {
      console.log(data);
      defer.resolve(fileName + ' success ');
    } else {
      defer.reject(fileName + ' fail ');
    }
  })

  return defer.promise;
}



Q.all([printFileContent('sample01.txt'), printFileContent('sample02.txt'), printFileContent('sample03.txt'),
    printFileContent('sample04.txt')
  ])
  .then(function(success) {
    console.log(success);
  }); //控制台打印各个文件内容 顺序不一定

Q.allSettled([printFileContent('nosuchfile.txt'), printFileContent('sample02.txt'), printFileContent('sample03.txt'), printFileContent('sample04.txt')])
  .then(function(results) {
    results.forEach(
      function(result) {
        console.log(result.state);
      }
    );
  });

结束promise链,有俩种结束方式:

1、返回最后一个promise。return foo().then(bar); 2、调用.done()来结束。foo().then(bar).done();。done()函数能把链中没有被处理的错误抛出。

/**
 *没有用done()结束的promise链
 *由于getPromse('2',2000,'opt')返回rejected, getPromise('3',1000)就没有执行
 *然后这个异常并没有任何提醒,是一个潜在的bug
 */
getPromise('1', 3000)
  .then(function() {
    return getPromise('2', 2000, 'opt')
  })
  .then(function() {
    return getPromise('3', 1000)
  });
/**
 *用done()结束的promise链
 *有异常抛出
 */
getPromise('1', 3000)
  .then(function() {
    return getPromise('2', 2000, 'opt')
  })
  .then(function() {
    return getPromise('3', 1000)
  })
  .done();

###should

api docs: http://shouldjs.github.io/

BDD式的测试框架。

添加自定的断言 使用should.Assertion.add方法,它接受3个参数: 1、方法名 2、断言的function。只检查positive case,对于.not的情况,should会handle。里面的this值向should.Assertion的实例; 3、boolean值,to mark if this assertion should be getter

对于2的function,里面的断言在检查前,必须先定义this.params。其格式为:{operator: , actual: , expected: }。下面俩种定义的方法:

1、第一种不被喜爱的,只是个shortcuts:

Assertion.add('true', function(){
  this.is.exactly(true)
}, true)

虽然这个没明确定义this.params,但相同的assertion调用.exactly会自动填充this.params的,不过这样做要小心。

2、这种是更值得推荐的做法:

Assertion.add('true', function(){
  this.params = {operator: 'to be true', expected: true};
  this.obj.should.be.exactly(true);
}, true)

这个就是定义了this.params,因为用了.should,故是用了新的assertion上下文。更多例子:

Assertion.add('asset', function(){
  this.params = {operator: 'to be asset'}
  this.obj.should.have.property('id').which.is.a.Number
  this.obj.should.have.property('path')
})

superagent

一个http库,可以发起getpost请求,用于抓取页面。使用示例:

superagent.get('https://cnodejs.org')
  .end(function(err, sres){
    // ...
  });

supertest

专门用来配合 express (准确来说是所有兼容 connect 的 web 框架)进行集成测试的,测试getpost请求,它与superagent是孪生库,API是一样的,使用示例:

var app = require('../app');
var supertest = require('supertest');
var request = supertest(app);

describe('test/app.test.js', function(){
  it('should return 55 when n is 10', function(done){
    // 这里之所以这个测试的 function 要接受一个 done 函数,是因为我们的测试内容
    // 涉及了异步调用,而 mocha 是无法感知异步调用完成的。所以我们主动接受它提供
    // 的 done 函数,在测试完毕时,自行调用一下,以示结束。
    // mocha 可以感到到我们的测试函数是否接受 done 参数。js 中,function
    // 对象是有长度的,它的长度由它的参数数量决定
    // (function (a, b, c, d) {}).length === 4
    // 所以 mocha 通过我们测试函数的长度就可以确定我们是否是异步测试。

    request.get('/fib')
      .query({n:10})
      .end(function(err, res){
        res.text.should.equal('55');
        done();
      });
  });
});

  • supertest(app)得到的request对象,有以下俩方法: 1、query()用来传querystring 2、send()用来传body,比如{title: 'modified title', tab: '0', content: 'detail'}

  • supertest利用supertest.agent(app).set('Cookie', 'a cookie string')实现Cookie持久化

    var supertest = require('supertest');
    var app = express();
    var agent = supertest.agent(app);
    
    agent.post('login').end(...);
    // then ..
    agent.post('create_topic').end(...); // 此时的 agent 中有用户登陆后的 cookie
    
    var supertest = require('supertest');
    var userCookie;
    supertest.post('login').end(function(err, res) {
      userCookie = res.headers['Cookie']
    });
    // then ..
    
    supertest.post('create_topic')
      .set('Cookie', userCookie)
      .end(...)
    

© 著作权归作者所有

共有 人打赏支持
前端届的科比
粉丝 21
博文 64
码字总数 51572
作品 0
深圳
一点感悟:《Node.js学习笔记》star数突破1000+

写作背景 笔者前年开始撰写的《Node.js学习笔记》 github star 数突破了1000,算是个里程碑吧。 从第一次提交(2016.11.03)到现在,1年半过去了。突然有些感慨,想要写点东西,谈谈这期间的...

程序猿小卡_casper ⋅ 06/06 ⋅ 0

细谈Node.js----我的笔记

学习心得 如何利用Javascript做为服务端脚本,通过Nodejs框架web开发。Nodejs框架是基于V8的引擎,是目前速度最快的 Javascript引擎。chrome浏览器就基于V8,同时打开20-30个网页都很流畅。N...

crossmix ⋅ 2016/01/04 ⋅ 0

cordova(一)cordova安装与创建一个简单项目

我刚开始接触cordova,在安装和配置环境的时候都是根据http://cordova.axuer.com/docs/zh-cn/latest/(cordova中文网)进行的,在这里做一下总结归纳。 关于cordova概述我这里就不写了,写了...

kunkun坤 ⋅ 2016/09/04 ⋅ 0

Centos 7 下 GitBook 的安装与使用

文前说明 作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。 本文仅供学习交流使用,侵权必删。 不用...

羽杰 ⋅ 2017/09/21 ⋅ 0

moro:一个用于追踪工作时间的命令行生产力工具

保持对你的工作小时数的追踪将让你知晓在一个特定时间区间内你所完成的工作总量。在网络上有大量的基于 GUI 的生产力工具可以用来追踪工作小时数。但我却不能找到一个基于 CLI 的工具。今天我...

作者: Sk ⋅ 05/07 ⋅ 0

nodejs资料索引

为什么要用node(说服你老板使用nodejs) convincing_the_boss links http://www.ibm.com/developerworks/cn/ 搜索“Node.js”和“BlueMix”关键字,有不少入门级的文章。 https://www.ibmdw....

cyper ⋅ 2014/03/29 ⋅ 0

NodeJS系列~第三个小例子,NodeJs与Redis实现高并发的队列存储

众所周知 redis量个强大的缓存组件,可以部署在win32和linux环境之上,它有五大存储结构,其中有一种为列表list,它可以实现quene和stack的功能,即队列和堆栈的功能。 redis相关文章,可以看...

mcy247 ⋅ 2017/12/06 ⋅ 0

Node.js开发入门—notepad++ for Node.js

对于Node.js开发,论IDE的话,Webstorm是不二的选择,但它是收费的(可免费使用30天)。一开始,我们先将就一下,使用notepad++来编写Node.js应用。这样做还有一大好处:没有关于Node.js的代...

foruok ⋅ 2015/09/12 ⋅ 0

学习NodeJS第一天:node.js引言

Node.JS 是资深 C 程序员 Ryan Dahl(http://four.livejournal.com/)的作品,依据 Google 著名的开源 JavaScript 引擎 V8 来进行二次开发的 Web I/O 服务器(http://nodejs.org/)。V8 本身...

sp42 ⋅ 2010/08/25 ⋅ 0

【Angular】之Angular环境搭建

前言 小编最近在学习angular的内容,万事开头难,完成了开头也便成功了一半。这句话小编在这次的学习实践之旅中,深有体会,下面小编就来讲一讲,angular环境搭建之旅吧! 一、环境搭建 1.下...

m18633778874 ⋅ 05/08 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Android JNI 读写Bitmap的方法

Java层创建Bitmap,通过JNI将Bitmap传到C/C++进行处理 Java部分 public static native boolean greenBitmap(Bitmap bitmap); C/C++部分 JNIEXPORT jboolean JNICALL Java_com_test_Test_gree......

国仔饼 ⋅ 23分钟前 ⋅ 0

一次性让你懂async/await,解决回调地狱

什么是async? 欢迎留言讨论 async 函数是 Generator 函数的语法糖。使用 关键字 async 来表示,在函数内部使用 await 来表示异步。相较于 Generator,async 函数的改进在于下面四点: 内置执...

阿K1225 ⋅ 24分钟前 ⋅ 0

angular常用命令

.下载更新操作 1.利用npm下载angular的命令行工具AngularCLI: npm install -g @angular/cli 2.下载jquery: npm install --save jquery 3.更新npm: npm i -g npm 4.更新angular: ng update ......

消散了的诗意 ⋅ 26分钟前 ⋅ 0

window.print 页面打印

定义和用法 print() 方法用于打印当前窗口的内容。 语法 window.print(); window.print() 实际上,是浏览器打印功能菜单的一种程序调用。与点击打印功能菜单一样,不能精确分页,不能设置纸型...

初学者的优化 ⋅ 27分钟前 ⋅ 0

魔兽世界 7.0版本上 PVE装备全攻略

  T套 因为大家应该都会打穿副本的所以具体是哪个boss我就不说了。   T1: 所有套装都在【熔火之心】出   T2: 头原来是在【奥妮克希亚的巢穴】改到黑翼之巢的奈法利安了,腿是在【熔火之...

wangchen1999 ⋅ 27分钟前 ⋅ 0

java.math.BigDecimal使用小结

原文地址 java.math.BigDecimal使用小结 divide方法 使用BigDecimal.divide方法时一定要考虑: 除数是否为0 商是否是无限小数 正确的使用方式 判断除数是否为0,是0做另外的处理逻辑 调用除法...

666B ⋅ 30分钟前 ⋅ 0

关于qstring转char乱码问题。

if (OpenClipboard(NULL)) { HGLOBAL hgClip; EmptyClipboard(); QByteArray byay = FValue.toLocal8Bit(); //转latin编码 char *bochsrc_line = byay.data(); hgClip = GlobalAlloc(GMEM_DD......

backtrackx ⋅ 30分钟前 ⋅ 0

了解SSH加密和连接过程

介绍 SSH或安全shell是安全协议,也是安全管理远程服务器的最常用方式。通过使用多种加密技术,SSH提供了一种机制,用于在双方之间建立加密安全连接,对彼此进行身份验证,以及来回传递命令和...

吴伟祥 ⋅ 37分钟前 ⋅ 0

微信小程序

小程序的全局配置app.json 微信小程序的全局配置保存在app.json文件中。开发者通过使用app.json来配置页面文件(pages)的路径、窗口(window)表现、设定网络超时时间值(networkTimeout)以...

上官清偌 ⋅ 40分钟前 ⋅ 0

【转】百度坐标坐标系之间的转换(JS版代码)

/** * Created by Wandergis on 2015/7/8. * 提供了百度坐标(BD09)、国测局坐标(火星坐标,GCJ02)、和WGS84坐标系之间的转换 *///定义一些常量var x_PI = 3.1415926535897932...

HAVENT ⋅ 41分钟前 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部