20181018前记
- 开始写nodeJs笔记,用于学习记录,通读一遍nodejs,记录知识点和不懂点,方便日后查看,所以内容基于官方文档,个别内容需要查找新资料,方便更好的理解,在查找资料的地方会注明出处~
- 编辑器使用sublime, 安装了插件nodeJs,这样 “command+b”就可以运行代码,且在console里面显示出来~,刚开始乱码,修改package里面nodejs中的Nodejs.sublime-build中的编码格式. encoding": "utf8" 即可
- 如果需要在sublime中实现node代码自动补全功能,需要安装SublimeCodeIntel,安装时间有点长,但是安装成功后,亲测有效~
- <font color="red">当前的node版本api是基于v9.11.2</font>
hello-world.js
第一个例子,普遍helloworld,很显然是创建了一个server用来输出Hello world,服务器端会打印出 当前运行的主机名和端口号:217.0.0.1 3000
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World!\n');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
assert-断言
“The assert module provides a simple set of assertion tests that can be used to test invariants.”官方的定义,但是翻译过来为“assert模块提供了一组简单的断言测试,可用于测试不变量”。很显然,第一次反复琢磨这句话,没懂。仔细通读后发现,应该是用于<font color="red">断言</font>,即:预期值和实际值的一个对比,如果不同,则会抛出异常或者错误,用于单元测试应该比较多,可以提前发现和排除错误
虽然assert支持两种模式legacy和strict,但是官方建议使用strict模式,legacy模式已经被弃用
下面是assert相关的api方法:
1.strict模式
const assert = require('assert').strict;
assert.deepEqual([[[1, 2, 3]], 4, 5], [[[1, 2, '3']], 4, 5]);
一开始执行的结果为<font color="blue">“TypeError: Cannot read property 'deepEqual' of undefined”</font>,查找了一下原因,发现我当时的node版本是8.几的,而我当前学习的node版本是9.几,所以,果然升级,升级过程如下:
sudo npm cache clean -f //清除nodejs的cache:
sudo npm install -g n //使用npm安装n模块
sudo n stable // 升级到稳定版本
成功安装到v10.12.0,再次执行上面assert的代码,就正常了~ 运行结果如下:
2.assert(value[, message]),assert.ok(value[, message])
assert()是assert.ok()的别名,所以直接研究assert.ok()就可以了
- assert.ok(value[, message]):测试value是否为真值。如果value不为真,则抛出一个带有message属性(message 属性的值等于传入的 message 参数的值)的AssertionError,如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。 如果没有传入参数,则 message 会被设为字符串 'No value argument passed to
assert.ok()
'。
const assert = require('assert').strict;
assert.ok(true) //正常运行
assert.ok(1) //正常运行
assert.ok() //AssertionError [ERR_ASSERTION]: No value argument passed to `assert.ok()`
assert.ok(false, '不是真值'); //AssertionError [ERR_ASSERTION]: 不是真值
assert.ok(typeof 123 === 'string');
/* AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert.ok(typeof 123 === 'string') */
assert.ok(0);
// 抛出 AssertionError: The expression evaluated to a falsy value:
//
// assert.ok(0)
// 同assert.ok(false);
assert(0);
/* AssertionError [ERR_ASSERTION]: The expression evaluated to a falsy value:
assert(0) */
3.assert.deepEqual(actual, expected[, message]),assert.deepStrictEqual(actual, expected[, message])
assert.deepEqual是 assert.deepStrictEqual()的别名,所以直接研究 assert.deepStrictEqual()就好
- assert.deepStrictEqual(actual, expected[, message])用来测试 actual 参数与 expected 参数是否深度相等。
- 如果两个值不相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。
const assert = require('assert').strict;
assert.deepStrictEqual({ a: 1 }, { a: '1' });
/*
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual
{
- a: 1
+ a: '1'
}
*/
assert.deepStrictEqual(NaN, NaN); //正常通过
assert.deepStrictEqual(0, -0);
/*
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual
- 0
+ -0
*/
4.assert.doesNotReject(asyncFn[, error][, message]) <font color='red'>该方法实际上没有多大作用</font>
等待asyncFn的promise,如果asyncFn是一个函数,则立即调用该函数并等待返回的promise完成。然后它将检查承诺是否被拒绝。
- 如果 asyncFn 是一个函数,并且同步抛出了一个错误, asser.doesNoReject()将抛出一个带有错误的被拒绝的promise。如果这个函数没有返回一个promise,assert.doesNotReject()将返回一个被拒绝的Promise,其中包含ERR_INVALID_RETURN_VALUE错误。在这两种情况下都会跳过错误处理程序。
- 注意:assert.doesNotReject()实际上没有用,因为通过捕获拒绝然后再次拒绝它几乎没有什么好处。相反,请考虑在不应拒绝的特定代码路径旁边添加注释,并尽可能保持表达错误消息。
- 如果指定,则错误可以是Class,RegExp或验证函数。有关更多详细信息,请参见<font color="red">assert.throws()。</font>
5.assert.doesNotThrow(fn[, error][, message]). <font color='red'>该方法实际上没有多大作用</font>
断言函数fn不会抛出错误。
- 请注意:使用assert.doesNotThrow()实际上没有用,因为捕获错误然后重新抛出它没有任何好处。相反,请考虑在特定代码路径旁边添加注释,该注释不应抛出并尽可能保持错误消息。
6.assert.fail([message])
抛出 AssertionError,并带上提供的错误信息或默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError.
- 其中fail带多个参数的方法已经被废弃
const assert = require('assert').strict;
assert.fail();
// 抛出 AssertionError [ERR_ASSERTION]: Failed
assert.fail('失败');
// 抛出 AssertionError [ERR_ASSERTION]: 失败
assert.fail(new TypeError('失败'));
/*
if (message instanceof Error) throw message;
TypeError: 失败
*/
7.assert.ifError(value)
如果value值不是undefined或者null,就抛出值,可用于测试回调函数的error参数。堆栈踪迹会包含传入ifError()的错误的所有帧,包括潜在的ifError()自身新增的帧。
const assert = require('assert').strict;
assert.ifError(undefined);
// 正常通过。 null也是正常通过
assert.ifError(0);
/*
throw newErr;
^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 0
*/
assert.ifError('错误信息');
/*
throw newErr;
^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: '错误信息'
*/
assert.ifError(new Error());
/*
throw newErr;
^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: Error
*/
let err;
(function errorFrame() {
err = new Error('错误信息');
})();
(function ifErrorFrame() {
assert.ifError(err);
})();
/*
throw newErr;
^
AssertionError [ERR_ASSERTION]: ifError got unwanted exception: 错误信息
*/
8.assert.notDeepStrictEqual(actual, expected[, message])
测试actual和expected是否深度严格的不平等。与assert.deepStrictEqual()相反。
- 如果两个值深度相等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则会分配默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。
const assert = require('assert').strict;
assert.notDeepStrictEqual({ a: 1 }, { a: '1' });
//正常通过
assert.notDeepStrictEqual({ a: 1 }, { a: 1});
/*
throw new AssertionError(obj);
^
AssertionError [ERR_ASSERTION]: Identical input passed to notDeepStrictEqual:
{
a: 1
}
*/
assert.notDeepStrictEqual({ a: 1 }, { a: 1}, "深度相等");
/*
throw new AssertionError(obj);
^
AssertionError [ERR_ASSERTION]: 深度相等
*/
9.assert.notEqual(actual, expected[, message]),assert.notStrictEqual(actual, expected[, message])
其中assert.notEqual()是assert.notStrictEqual()的别名,所以直接研究assert.notStrictEqual()就好
- 结合SameValue比较方法,判断actual和expected的值是否不全等
- 如果两个值全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。
10.assert.rejects(asyncFn[, error][, message])
等待asyncFn 的 promise,如果asyncFn是一个函数,则立即调用该函数并等待返回的promise完成。然后它将检查promise是否被拒绝。
- 注意:除了等待的异步性质之外,完成行为与assert.throws()完全相同。
11.assert.strictEqual(actual, expected[, message])
使用 SameValue比较法测试 actual 参数与 expected 参数是否全等。
- 如果两个值不全等,则抛出一个带有 message 属性的 AssertionError,其中 message 属性的值等于传入的 message 参数的值。 如果 message 参数为 undefined,则赋予默认的错误信息。 如果 message 参数是 Error 的实例,则会抛出它而不是 AssertionError。
12.assert.throws(fn[, error][, message])
期望函数fn抛出错误。
- 如果特意指定的话,则错误可以是Class,RegExp,验证函数,验证对象,其中每个属性将被测试严格的深度相等,或者错误的实例,其中每个属性将被测试是斗严格的深度相等,包括不可枚举的消息和名称属性。
- 使用对象时,在对字符串属性进行验证时,也可以使用正则表达式。
- 如果fn调用无法抛出或错误验证失败,则消息将附加到AssertionError提供的消息。
- 自定义验证对象/错误实例:
const assert = require('assert').strict;
const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
nested: true,
baz: 'text'
};
err.reg = /abc/i;
<!-- 仅测试验证对象上的属性。 -->
<!-- 使用嵌套对象需要存在所有属性。否则验证将失败 -->
assert.throws(
() => {
throw err;
},
{
name: 'TypeError',
message: 'Wrong value',
info: {
nested: true,
baz: 'text'
}
}
);
<!-- 测试通过 -->
assert.throws(
() => {
throw err;
},
{
name: 'TypeError',
message: 'Wrong value',
info: {
nested: true,
baz: 'test'
}
}
);
<!-- AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual ... Lines skipped
Comparison {
info: {
- baz: 'text',
+ baz: 'test',
nested: true
...
name: 'TypeError'
} a: 1
} -->
assert.throws(
() => {
throw err;
},
{
name: 'TypeError',
message: 'Wrong value',
info: {
nested: true,
// baz: 'test'
}
}
);
<!--
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual ... Lines skipped
Comparison {
info: {
- baz: 'text',
nested: true
...
name: 'TypeError'
}
-->
const assert = require('assert').strict;
const err = new TypeError('Wrong value');
err.code = 404;
err.foo = 'bar';
err.info = {
nested: true,
baz: 'text'
};
err.reg = /abc/i;
<!-- 使用正则表达式验证错误属性: -->
assert.throws(
() => {
throw err;
},
{
<!-- The `name` and `message` properties are strings and using regular
expressions on those will match against the string. If they fail, an
error is thrown. -->
name: /^TypeError$/,
message: /Wrong/,
foo: 'bar',
info: {
nested: true,
// It is not possible to use regular expressions for nested properties!
baz: 'text'
},
<!-- The `reg` property contains a regular expression and only if the
validation object contains an identical regular expression, it is goingto pass. -->
reg: /abc/i
}
);
<!-- 通过 -->
// 由于`message`和`name`属性不同而失败:
assert.throws(
() => {
const otherErr = new Error('Not found');
otherErr.code = 404;
throw otherErr;
},
err // This tests for `message`, `name` and `code`.
);
<!--
AssertionError [ERR_ASSERTION]: Input A expected to strictly deep-equal input B:
+ expected - actual
Comparison {
code: 404,
- message: 'Not found',
- name: 'Error'
+ foo: 'bar',
+ info: {
+ baz: 'text',
+ nested: true
+ },
+ message: 'Wrong value',
+ name: 'TypeError',
+ reg: /abc/i
}
-->
- 自定义错误验证
assert.throws(
() => {
throw new Error('Wrong value');
},
function(err) {
if ((err instanceof Error) && /value/.test(err)) {
return true;
}
},
'unexpected error'
);
- 请注意,错误不能是字符串。如果提供了一个字符串作为第二个参数,则假定错误被忽略,而字符串将用于消息。这可能导致easy-to-miss的错误。 使用与抛出的错误消息相同的消息将导致ERR_AMBIGUOUS_ARGUMENT错误。如果使用字符串作为第二个参数,请仔细阅读下面的示例:
const assert = require('assert').strict;
function throwingFirst() {
throw new Error('First');
}
function throwingSecond() {
throw new Error('Second');
}
function notThrowing() {}
//第二个参数是一个字符串,输入函数抛出一个错误。
//第一种情况不会抛出,因为它与错误消息不匹配,所以不会抛出异常,顺利执行
assert.throws(throwingFirst, 'Second');
// 在下一个示例中,消息对来自错误的消息没有任何好处,并且由于不清楚用户是否打算实际匹配错误消息,因此Node.js抛出了“ERR_AMBIGUOUS_ARGUMENT”错误。
assert.throws(throwingSecond, 'Second');
/*
hrow new ERR_AMBIGUOUS_ARGUMENT(
^
TypeError [ERR_AMBIGUOUS_ARGUMENT]: The "error/message" argument is ambiguous. The error message "Second" is identical to the message.
*/
// 该字符串仅在函数未抛出时使用(作为消息):
assert.throws(notThrowing, 'Second');
/*
throw new AssertionError(obj);
^
AssertionError [ERR_ASSERTION]: Missing expected exception: Second
*/
// 如果它打算匹配错误消息,请改为下面这样,并且不抛出因为错误消息匹配。
assert.throws(throwingSecond, /Second$/); //顺利通过执行
assert.throws(throwingFirst, /Second$/);
/*
throw actual;
^
Error: First
*/
- <font color="red"></font>由于令人困惑的表示法,建议不要使用字符串作为第二个参数。这可能会导致难以发现的错误