nodejs学习笔记5

来源:互联网 发布:java打字小游戏源代码 编辑:程序博客网 时间:2024/06/06 20:43

测试模块

选取node中的node-tap工具进行异步测试。
将node-tap包含进package.json文件的dev-dependencies就可安装它:

{    "name":"myApp",    "version":"0.1.0",    "devDependencies"{        "tap":"*"    }}

然后执行命令:npm install
注:devDependencies属性是声明只用于开发和测试应用程序的依赖模块。
当在产品模式下安装应用程序时,可以使用-production选项跳过安装devDependencies所列的模块。
npm install -production

编写测试

一般来说创建一个tests目录放置测试脚本,且每个要测试的模块都包含一个文件。首先获得test构造函数:

var test = require('tap').test;//定义一个测试。传入测试名和一个包含测试代码的函数test("addtion of 2 and 2 works",function(t){    t.equal(2+2,4,"2+2 should be 4");    t.end();});

参数t包含面向测试的控制对象。利用该对象可以测试是否符合你的期望。并结束当前测试。
运行测试:node my_test.js.即可得到结果

使用断言测试模块

导入assert模块:

var assert = require('assert');var a = true;assert(a);//可以传入一个消息来在测试失败时提供更多的显示信息assert(a,"a should be truthy");//相当于js的“==”操作符assert.equal('10',10,'should be equal');//相当于js的“===”操作符assert.strictEqual('10',10,'string 10 should be equas to number 10');assert.notEqual('10',10,'should be equal');assert.notStrictEqual('10',10,'string 10 should be equas to number 10');

每一个断言函数都会设置一个期望条件,如果期望条件不满足则会抛出一个异常。
如果想测试两个对象,则这两个对象的引用必须指向同一个对象才会相等。

assert.equal({a:1},{a:1});//抛出异常

如果想比较对象的属性,就要用到深比较:

var obj = {b:1,a:[1,2,3]};assert.deepEqual(obj,{a:[1,2,3],b:1});//不会抛出异常

deepEqual函数验证的仅仅是对象的可枚举属性。如果两个对象具有不同的原型,但是他们的所有可枚举属性相同,他们就不会表现出不同。

使用node-tap中的内置断言函数

用它来代替Node核心模块中的断言函数可好处是:可以查看测试计数,错误报告,合计报告等。

test('truthyness of numbers',function(t){    //测试值是否为真    t.ok(1,'1 should be truthy');    //测试值是否为假    t.notOk(0,'0 should not be truthy');    t.end();});//t.equal函数测试严格相等性或浅相等性:test('sum works',function(t){    var a = 2=2t.equal(a,'4','2+2 should be 4');//断言失效    t.notEqual(a,4,'2+2 should not be 4');    t.end();});//等价性测试test('object equivalency',function(t){    var a = {a:1,b:2};    t.equivalent(a,{b:2,a:1});    t.end();});//判断一个对象是否包含一系列属性test('object similarity',function(t){    var a = {a:1,b:2};    t.similar(a,{a:1});    t.end();});//测试对象类型test('object type',function(t){    t.type(1,"number");    t.end();})

控制回调流程

可以使用ASYNC控制库来控制回调流程。首先安装async模块:
npm install async.
下面实现一个给定数值平方的HTTP服务器。

var port = 8080;require('http').createServer(function(req,res){    var body = "";    req.setEncoding('utf8');    req.on('data',function(data){        body += data;    });    req.once('end',function(){        var number = JSON.parse(body);        var squared = Math.pow(number,2);        res.end(JSON.stringify(squared));    });}).listen(port,function(){    console.log('squaring server listening on port 8080');});

串行执行

可以利用async.series函数将两个I/O操作串接起来。

var async = require('async'),    request = require('request');function done(err,results){    if(err){throw err;}    console.log('results:%j',results);}async.series({    function(next){        request.post({uri:'http://localhost:8080',body:'4'},            function(err,res,body){                next(err,body && JSON.parse(body));            }         );    },    function(next){        request.post({uri:'http://localhost:8080',body:'5'},            function(err,res,body){                next(err,body && JSON.parse(body));            }         );    }},done);

所有函数都结束后,会调用回调函数done,此时done函数带有每个回调函数的异步结果。以上执行后的结果为:results:[16,25].

并发执行

只要将上述例子的async.series改为async.parallel即可并发执行回调函数。

连续传递

如果下一个回调函数的执行取决于前一个回调函数结果。就可使用async.waterfall函数。

function done(err,res,body){    if(err){throw err;}    console.log('3^4=%d',body);}async.waterfall([    function(next){        request.post({uri:'http://localhost:8080',body:'3'},next);    },    function(res,body,next){        request.post({uri:'http://localhost:8080',body:body},next);    }],done);

排队

控制在给定时刻同时存在的正在进行作业的最大数量就可使用async.queue函数。该函数创建一个队列,基于一个函数处理其中的元素。队列的客户端将作业和并发的最大数量传入这个函数,按照顺序执行每个作业。

function done(err,results){    if(err){throw err;}    console.log('results:%j',results);};var maximumConcurrency = 5;function worker(task,callback){    request.post({uri:'http://localhost:8080',body:JSON.stringify(task)},            function(err,res,body){                callback(err,body && JSON.parse(body));            }         );}var queue = async.queue(worker,maximumConcurrency);[1,2,3,4,5,6,7,8,9,10].forEach(function(i){    queue.push(i,function(err,result){        if(err){throw err;}        console.log(i+'^2=%d',result);    });});

队列被创建之后可以修改最大并发数:

queue.concurrency = 10;

当队列达到最大并发数时,可以将一个函数赋给队列的saturated属性来监听:

queue.saturated = function(){    console.log('queue is saturated');};//也可以监听empty事件queue.empty = function(){    console.log('queue is empty');};//当返回作业的最后一项作业时,队列会发射drain事件queue.drain = function(){    console.log('queue is drained, no more work');};

迭代

var results = {};function done(err){    if(err){throw err;}    console.log('done!results:%j',results);}var collection = [1,2,3,4];function iterator(value,callback){    request.post({        uri:'http://localhost:8080',        body:JSON.stringify(value)    },    function(err,res,body){        if(err) return callback(err);        results[value] = JSON.parse(body);        callback();    });}async.forEach(collectino,iterator,done);

当在所有元素完成了异步迭代之后,就会调用最后一个函数,即done。
如果向同步迭代可以使用async.forEachSeries(collection,iterator,done)函数。
如果向在异步迭代时控制最大并发数,可以使用async.forEachLimit():

var maximumConcurrency = 5;async.forEachLimit(collection,maximumConcurrency,iterator,done);

映射

function done(err,results){    if(err){throw err;}    console.log('done!results:%j',results);}var collection = [1,2,3,4];function iterator(value,callback){    request.post({        uri:'http://localhost:8080',        body:JSON.stringify(value)    },    function(err,res,body){        callback(err,body&&JSON.parse(body));    });}async.map(collection,iterator,done);

async.map()函数将每个结果传递给迭代函数中的回调函数,获得所有结果后按照正确的顺序将结果提交给done函数。

规约

与javascript的array.reduce()函数类似,不过他是异步执行的。

var collection = [1,2,3,4];function done(err,results){    if(err){throw err;}    console.log('the sum of the squares of %j is %d',collection,results);}function iterator(memo,item,callback){    request.post({        uri:'http://localhost:8080',        body:JSON.stringify(item)    },    function(err,res,body){        callback(err,body&&(memo+JSON.parse(body)));    });}//第二个参数为初始值。然后在集合上的每个集合迭代,当一次迭代结束时,就将一个新的memo值传入回调函数,再加上memo原来的值async.reduce(collection,0,iterator,done);

过滤

在js中可以对基于一个函数对集合进行过滤。async.filter可以异步执行相同的操作。

var collection = [1,2,3,4,5];function done(result){    console.log('these are the elements whose square value is greater than 10:%j',result);}function test(value){    return value>10;}function filter(item,callback){    request.post({        uri:'http://localhost:8080',        body:JSON.stringify(item)    },    function(err,res,body){        callback(body && test(JSON.parse(body)));    });}async.filter(collection,filter,done);还有一个与filter作用相反的函数:async.reject(collection,filter,done);

检测

当满足某个条件时,想停止迭代。例如检测集合中第一个平方大于10的数。

var collection = [1,2,3,4,5];function done(result){    console.log('the firsr element whose square value is greater than 10:%j',result);}function test(value){    return value>10;}function detect(item,callback){    request.post({        uri:'http://localhost:8080',        body:JSON.stringify(item)    },    function(err,res,body){        callback(body && test(JSON.parse(body)));    });}async.detect(collection,detect,done);//可以使用detect的串行版本async.detectSeries(collection,detect,done);
0 0
原创粉丝点击