今天的课主要讲了callback与正则表达式。
callback
callback:主要是callback hell的历史问题与callback hell的解决方案
error-first:node异步回调规范,将error参数作为第一位。
// error-first 函数
(err, value) => {
}
util.callbackify:接收一个async函数(或者接收返回一个Promise对象那个的函数),并返回一个遵循error-first回调风格的函数。
const util = require('util');
// async function:
async function fn() {
return 'hello world!';
}
const callback = util.callbackify(fn);
callback((err, ret) => {
if(err) throw err;
console.log(ret);
})
// Promise function:
function fn() {
return Promise.reject(null);
}
const callback = util.callbackify(fn);
callback((err, ret) => {
err && err.hasOwnProperty('reason') && err.reason === null;
})
生成器generator function,符合可迭代协议和迭代器协议。
// function* 生成器函数
function* gen() {
yield 1;
yield 2;
yield 3;
}
let g = gen();
// 返回一个yield表达式生成的值
Generator.prototype.next()
// 返回给定值,并结束生成器
Generator.prototype.return()
// 向生成器抛出一个错误
Generator.prototype.throw()
// 常用方法
g.next().value; // 当前yield的值
g.next().done; // 迭代器是否结束
es6新标准Promise + async/await:
function resolveAfter2000ms() {
return new Promise((resolve, reject) => {
setTimetout(() => { resolve('1') }, 2000)
})
}
async function asyncCall() {
console.log('calling asyncCall: ');
// 执行asyncCall函数,会返回resolveAfter2000ms函数的值。
// 但是在asyncCall函数中执行的resolveAfter2000ms函数,则会返回resolve的值。
var result = await resolveAfter2000ms();
console.log(result);
}
promisify: 接收一个error-first格式的函数,并返回一个Promise格式的对象。
const util = require('util');
const fs = require('fs');
// fs.stat满足最后一个参数是callback并且满足first-error的函数
const stat = util.promisify(fs.stat);
// promise风格
stat('.').then((stats) => {
// do something
}).catch((err) => {
// alert error
})
// async/await风格
async function callStat() {
var stats = await stat('.');
console.log(stats);
}
关于 管道 & Stream:
其实这部分并没有完全吃透,看的内容也主要是解耦,KISS和拼装。主要是为了程序的灵活和模拟日常生活中的零件化。说白了就是跟插座一样,你一开始插的风筒,后面拔了插电热水壶,完全是不受影响,可以正常使用的。
正则表达式
关于 正则表达式:
主要讲了历史以及匹配字符的用法。
元字符
.:匹配 除换行符 以外的 任意字符 。
\w:匹配 字母 或 数字 或 下划线 。
\W:匹配不是 字母、数字、下划线 的字符。
\d:匹配 数字,相当于 [0-9]。
\D:匹配 非数字 的字符。
\s:匹配任意 不可见字符,包括 空格、制表符、换行符 等。
\S:匹配任意 可见字符 。
^:匹配字符串的 开始位置 。
$:匹配字符串的 结束位置。
量词:
*:重复 任意次,相当于 {0,}。
?:重复 0次 或 1次,相当于 {0,1}。
+:重复 1次 或 更多次,相当于 {1,}。
{n}:重复 n次。
{n,}:重复 n次 或者 大于n次。
{n,m}:重复 n 到 m 次。
分支 & 字符集:
分支:(a|b|c)。
字符集:符号为 [abc] === [a-c],[^abc] === [^a-c]。
分组 & 引用:
分组:符号为 ()。
分组例子:/(\d{4})-(\d{2})-(\d{2})/,一共3个括号,分了三组。
/(\d{4})-(\d{2})-(\d{2})/.match('2018-03-12');
// 会得到1个完整的匹配和3个分组。
// '2018-03-12' => 完整的匹配
// '2018' => 第一个分组
// '03' => 第二个分组
// '12' => 第三个分组
引用:默认为 \+数字,比如 \1 or \2 or \3。
引用例子:/(\d{4})-(\d{2})-\2/,一共2个括号,1个引用,这里要注意,引用第2个,就必须匹配跟第2个引用一模一样的值。
/(\d{4})-(\d{2})-\2/.match('2018-03-03');
=> true
/(\d{4})-(\d{2})-\2/.match('2018-03-04');
/(\d{4})-(\d{2})-\2/.match('2018-03-02');
/(\d{4})-(\d{2})-\2/.match('2018-03-11');
/(\d{4})-(\d{2})-\2/.match('2018-03-12');
=> false
零宽断言,环视,lookaround assertions:
可在当前位置 向前 或者 向后 匹配,并且 不占字符串宽度 的正则匹配。
| 正向匹配→ | 逆向匹配 ← | |
|---|---|---|
| 肯定 | (?=pattern) | (?<=pattern) |
| 否定 | (?!pattern) | (?<!pattern) |
/ab(?=c)d/.test('abcde');
=> false
// 注释:
// 如果lookaround assertions是占用宽度,那test函数返回的肯定是true。
// 但是这里返回的是false,说明ab(c)d中并不能匹配字符串的abcde,所以它是不占用宽度的。
惰性模式 & 贪婪模式:
| 贪婪模式 | 惰性模式 |
|---|---|
| 尽可能多的去匹配 | 尽可能少的去匹配 |
| 默认 | 加个问号 |
| .*, .+, .? | .*?,.+?,.?? |
修饰符 & 标志:
| 修饰符 | 全名 | 意义 |
|---|---|---|
| g | global | 全局搜索 |
| i | ignoreCase | 不区分大小写 |
| m | multiline | 多行搜索 |
| y | sticky | “粘性”搜索 |
编不下去了…完。