0%

JavaScript代码是单线程运行的,因而一旦有未捕获的异常抛出线程就会挂掉,业务也就不可访问了,所以一般我们在使用koa,express,thinkjs等其他node框架时一般会使用pm2去管理node进程,保证业务的高可用性。而阿里开源的egg框架本身自带的egg-cluster模板已经帮我们做了这个事情,egg的多进程模型和进程间通信官方文档上写的已经很清楚了,今天学习一下源码,希望有所收获。

egg-bin dev

运行一个egg项目,npm run dev在package.json文件里我们发现默认其实执行的是egg-bin dev。egg-bin原来是egg提供的一个开发时使用的命令行工具,翻开egg-bin的代码,我们可以看到egg-bin其实是基于common-bin开发的,这里不赘述common-bin的用法,感兴趣的童鞋自行去查阅。在lib/cmd/dev.js里我们可以看到egg-bin dev执行的逻辑(去掉debug日志):

阅读全文 »

依稀记得第一次接触Vue.$nextTick是在之前某个项目从Vue 1.x升级到Vue 2.x时,发现vue实例的生命周期钩子函数都变了。查阅Vue官方提供的升级文档时发现,ready被mounted钩子函数替代,文档还特别提出,mounted并不保证钩子函数中的this.$el在document中,需要使用vm.$nextTick,那时起就觉得$nextTick好神奇。今天就来谈(xia)谈(che)Vue的异步实现$nextTick。

0 浏览器事件循环机制

在谈$nextTick之前,当然要先温习一下浏览器的事件循环啦。ps:各位对浏览器事件循环机制了如指掌的看官可以直接跳过了。

0.1 单线程和异步

我们都知道js是单线程的,js引擎负责解释执行js的只有一个线程,就是我们所谓的主线程,而一些异步回调函数会被放到任务队列中,当主线程空闲时,会执行任务队列中的回调函数。

0.2 tasks (macroTasks) 和 microTasks

event loop中有两种类型的任务队列,tasks(macroTasks)和mircroTasks。

  • tasks: 执行主线程js代码、网络请求、页面加载、输入、点击事件以及定时器事件(setTimeout,setIntervel,setImmediate)等。
  • microTasks: 更新应用程序状态的任务,常见的有promise,process.nextTick,MutationObserver,Object.observe等
阅读全文 »

在kali2上安装vnc server的过程中遇到一些问题,记录总结下

  • 安装vnc server,选择vnc4server,执行命令
    1
    sudo apt-get install vnc4server
  • 首次启动vncserver 执行命令
    1
    sudo vncserver
  • 首次启动,需要输入密码和验证密码,以及一个是否设置【只读】密码,会保存在~/.vnc/passwd中
  • 启动时,往往会报错,此时在~/.vnc/中查看是否有xstartup文件,没有新增一个,默认可以写入
    1
    2
    3
    $ cat ~/.vnc/xstartup 
    #!/bin/sh
    xterm &
  • 在vnc viewer中连接vnc server,ip+桌面号或者端口号,
阅读全文 »

看汤姆大叔的博客,记录一下对象创建模式里的沙盒模式
沙盒模式即是为一个或多个模块提供单独的上下文环境,而不会影响其他模块的上下文环境,比如有个Sandbox里有3个方法event,dom,ajax,在调用其中2个组成一个环境的话,和调用三个组成的环境完全没有干扰。Sandbox实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

function Sandbox() {
var args = Array.prototype.slice.call(arguments),
//最后一个参数为callback
callback = args.pop(),
//除最后一个参数外,其他均为要选择的模块
modules = (args[0] && typeof args[0] === 'string') ? args : args[0],
i;

//强制使用new 操作符
if(!(this instanceof Sandbox)) {
return new Sandbox(modules, callback);
}

//添加属性
this.a = 1;
this.b = 2;

//向this对象上添加模块
//如果没有传模块或者传入的参数为"*",则认为传入所有模块
if(!modules || modules == '*') {
modules = [];
for(i in Sandbox.moduls) {
if(Sandbox.modules.hasOwnProperty(i)) {
modules.push(i);
}
}
}

//初始化需要的模块
for(i = 0; i<modules.length; i+=1) {
Sandbox.modules[modules[i]](this);
}

//调用callback
callback(this);
}

//默认添加原型对象
Sandbox.prototype = {
name: 'My Application',
version: '1.0',
getName: function() {
return this.name;
}
}
阅读全文 »

记录迭代器模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

var agg = (function() {
var index = 0,
data = [1,2,3,4,5],
length = data.length;
return {
next: function() {
var element;
if(!this.hasNext()) {
return null;
}
element = data[index];
index = index + 1;
return element;
},
hasNext: function() {
return index < length;
},
rewind: function() {
index = 0;
},
current: function() {
return data[index];
}
}
})();

while(agg.hasNext()) {
console.log(agg.next())
}

看汤姆大叔的博客,记录学习下订阅、发布模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

function Event(name) {
var handlers = [];

this.getName = function() {
return name;
};

this.addHandler = function(handler) {
handlers.push(handler)
};

this.removeHandler = function(handler) {
for(var i = 0; i< handlers.length; i++) {
if(handlers[i] == handler) {
handlers.splice(i, 1);
break;
}
}
};

this.fire = function(eventArgs) {
handlers.forEach(function(h) {
h(eventArgs);
});
};
}
阅读全文 »

将#ffffff转化成rgb(255,255,255)

1
2
3
4
5
function colorTranslator(str) {
var arrColor = str.slice(1).match(/\w{2}/g)
return 'agb('+ arrColor.map(item => parseInt(item, 16) || 0).join(',') +')'
}
console.log(colorTranslator('#ffffff'))
阅读全文 »