解决ElementaryOS 下 Intel显卡接多屏时偶尔会闪屏的 bug

根据:https://bugs.launchpad.net/elementaryos/+bug/1435861

作如何更改:

sudo apt-get install mesa-utils
sudo mkdir /etc/X11/xorg.conf.d/
echo -e 'Section "Device"\n Identifier "Intel Graphics"\n Driver "Intel"\n Option "AccelMethod" "sna"\n Option "TearFree" "true"\nEndSection' | sudo tee /etc/X11/xorg.conf.d/20-intel.conf
sudo reboot
Share Comments

64位ElementaryOS(Ubuntu)配置cordova/ionic

1. JDK

JDK 比较简单,直接在官网下载即可 。

2. ANDROID SDK

ANDROID SDK 非常地费劲!伟大的墙各种添堵!我是先通过 ssh 把压缩包 wget 到 vps 上(wget三百多m十秒下完,美帝的网速太腐败了),再下载到本地。这样速度会比通过 vpn 的稍快些。

3. 两个巨大的包下载后解压,然后设置环境变量

1
$ vim ~/.bashrc

加入以下变量:

1
2
3
export JAVA_HOME=/path/to/jdk
export ANDROID_HOME=/path/to/android_sdk
export PATH=${PATH}:${JAVA_HOME}/bin:${ANDROID_HOME}/platform-tools:${ANDROID_HOME}/tools

刷新

1
$ source ~/.bashrc

4. 安装 Android SDK 的组件

包括一些基本依赖和版本相关的镜像。这个只能联上VPN搞了。不翻墙是行不通的。联上后回到 shell, 打入

1
$ android

这个是 sdk 管理器,加载好后,默认会自动选上基础包和最新的 android 所有的镜象。考虑到网速,建议在“版本”如 Android x.x.x (API xx),下面,选中 SDK Platform 和 ARM EABI xxx System Image 这两个包就可以了,但如果你的电脑支持虚拟化,可以把 ARM 架构的换成 Atom x86-64位的,再装好 kvm ,速度会快很多。我选的就是 Atmo x86-64。

下载好镜像之后,在 Tools -> Manage AVDs -> Create 新建一个虚拟机器,后面的 ionic emulate 会用到

4.1 安装 KVM (仅限支持虚拟化的机器)

1
$ cat /proc/cpuinfo

若输出的 flags 中有 vmx(INTEL) 或 svm(AMD) 的话即是支持

1
$ sudo apt-get install qemu-kvm virt-manager bridge-utils libvirt-bin

装完看下有没有 /dev/kvm 若没有,重启进 bios 开启虚拟化。(我的笔记本设置开启虚拟化后还需要冷启动才能生效)

4.2 安装 Android SDK 依赖

由于 Android SDK 很多工具都是32位的,我的系统是 64 位,还需要一些依赖,否则无法会导致 cordova 无法build:

<span class="pln">$ sudo apt</span><span class="pun">-</span><span class="kwd">get</span><span class="pln"> install libncurses5</span><span class="pun">:</span><span class="pln">i386 libstdc</span><span class="pun">++</span><span class="lit">6</span><span class="pun">:</span><span class="pln">i386 zlib1g</span><span class="pun">:</span><span class="pln">i386
</span>

装完以上的库可以解决 cordova 的 build 问题。

接下来还要解决 emulate 的问题。

1
2
3
$ cd ${ANDROID_HOME}/tools
$ rm emulator
$ ln -s emulator64-x86 emulator

总之 emulator 的架构要和 image 对应。

5. Node.js 的版本

实测 v5.0.0 是不行的, v0.12.7/v4.2.1 可以,建议使用 nvm 管理 node.js 版本。

6. 安装 cordova 与 ionic

ionic 依赖 node-sass ,node-sass 需要 g++,先安装 g++

1
2
$ sudo apt-get install g++
$ npm install -g cordova ionic

7. 好了,测试一下

1
2
3
4
$ ionic start myApp tabs
$ ionic platform add android
$ ionic build android
$ ionic emulate

:)

8. 真机调试

emulator 不给力,速度慢调试麻烦。直接用手机调试效果更加直观,只要安卓4.1以上版本,在设置里打开USB调试,接入到电脑上,就可以开搞了。

$ ionic build && ionic run

手机会提示安装,点击同意,程序就会安装并开始运行了。然后打开 chrome,在地址栏输入:

chrome://inspect/#devices

注可以看到手机设备,点击 inspect ,这个调试界面就不用多讲了吧!

Share Comments

ubuntu 搭建VPN Server - 浪漫小生 - 博客园

Source: ubuntu 搭建VPN Server - 浪漫小生 - 博客园

废话不多说,直接上步骤:

  1. 以 root 账户登录 VPS,或者当你运行下列命令提示权限不够时,加上 sudo 再运行。
  2. 安装 PPTPD:
    编辑 /etc/pptpd.conf 文件,取消注释以下 2 行:

    1
    2
    localip 192.168.0.1
    remoteip 192.168.0.234-238,192.168.0.245
  3. 添加 PPTP 账户:
    编辑 /etc/ppp/chap-secrets 文件,按如下格式添加:

    1
    用户名 pptpd "密码" 允许接入的IP

    其中密码要用引号包围。允许任何 IP 接入则用 * 号表示。

  4. 设置 DNS Server:
    编辑 /etc/ppp/pptpd-options 文件,找到 ms-dns 部分来修改,我使用的是 Google 的:

    1
    2
    ms-dns 8.8.8.8
    ms-dns 8.8.4.4
  5. 开启 IP 转发:
    编辑 /etc/sysctl.conf 文件,取消注释该行:

    1
    net.ipv4.ip_forward=1

    然后运行这行代码使配置生效:

    1
    sysctl -p
  6. 安装 iptables:

    1
    2
    3
    apt-get install iptables
    iptables -t nat -I POSTROUTING -j MASQUERADE
    sudo iptables-save &gt; /etc/iptables-rules
  7. 自动加载配置:

    修改 /etc/network/interfaces 文件,找到 eth0 那一节,在对 eth0 的设置最末尾加上下面这句:

    1
    pre-up iptables-restore > /etc/iptables-rules
  8. 重启 pptpd:

    1
    /etc/init.d/pptpd restart
Share Comments

为Node.js4配置VIM编辑器

安装必要插件:

pathogen 插件管理

主页:https://github.com/tpope/vim-pathogen

有了这个,就可以像 Textmate / Sublime Text 那样方便地安装卸载插件。后面安装的插件只需将它们放到 ~/.vim/bundle/ 里面独立一个文件夹,pathogen 更会自动加载。卸载时进入到 ~/.vim/bundle/ 找到对应的文件夹删除即可!干净利落。

mkdir -p ~/.vim/autoload ~/.vim/bundle &amp;&amp; \ curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim

然后在 ~/.vimrc 加入:

execute pathogen#infect()

auto-pairs 自动配对

主页:https://github.com/jiangmiao/auto-pairs

当输入(时会自动补齐),包括中括号,尖括号等。删除的时候更会自动删除右边对应的配对符号。需要在括号之间加一对空格也只需要按一下空格就行。

git clone git://github.com/jiangmiao/auto-pairs.git ~/.vim/bundle/auto-pairs

vim-closetag 自动关闭 HTML 标签

主页:https://github.com/alvan/vim-closetag

snipmate 的html标签太少了,不实用。自动化的更合适,当输入 时会自动补全 。

git clone https://github.com/alvan/vim-closetag.git ~/.vim/bundle/vim-closetag

安装完成之后在 ~/.vimrc 加入配置,指定生效的文件扩展名:

let g:closetag_filenames = "*.html,*.xhtml,*.phtml"

vim-surround 智能包围

主页:https://github.com/tpope/vim-surround

在 Sublime Text 中,如果你选定一段文字。按一下’键或”等有包含意义的按键,编辑器会自动在尾部帮你追加一个对应的结束符。这个插件不但可以完成类似的功能还更加地强大!替换括号,再增加一层括号,追加。都不是问题!并且 html tag 的包含也是支持的哇!

git clone git://github.com/tpope/vim-surround.git ~/.vim/bundle/vim-surround

nerdcommenter 快速注释

主页:https://github.com/scrooloose/nerdcommenter

安装:

git clone https://github.com/scrooloose/nerdcommenter ~/.vim/bundle/nerdcommenter

快速切换注释代码。可视模式下,当前行或选中行后按以下按键进行切换:

\cc 注释 \cs “性感注释",貌似在js里面就是函数说明的注释样式 \cu 撤销注释 \ci 按行切换注释

vim-repeat 自动重复插件

主页:https://github.com/tpope/vim-repeat

这个有点类似宏的东西,配合 vim-surround 功能无比强大。比如说你现在要把 js 中声明的 { a: 'foo': b: 'bar', c: ...} 转化成为一个标准的 json 文档,那么,需要将 a,b,c…加上双引号,’foo’,’bar’,…转换为双引号。利用 vim-surround 可以追加和替换,但是每一次重复打 ysiw” 和 cs’” 也是挺麻烦的。vim-repeat 可以自动帮你重复上一次的命令。只要将光标定位到对应的单上面再按一下.键,命令就自动重复!

git clone git://github.com/tpope/vim-repeat.git ~/.vim/bundle/vim-repeat

NERDTree 文件管理器

主页:https://github.com/scrooloose/nerdtree

即是在侧栏显示一个树型的文件浏览器,几乎稍微现代些的代码编辑器都是内置的。但对于VIM来讲,这个功能还是需要加个插件才能实现。由于要考虑到 shell 环境,这个在 gvim + tab 的环境体验并不良好。但在单 tab 模式下。该有的功能还是一样不少,比 Sublime text 和 Textmate 的文件管理功能都要强大。书签,定义根目录,新建,删除,重命名,移动都是有的。鼠标或键盘操作都支持!

git clone https://github.com/scrooloose/nerdtree.git ~/.vim/bundle/nerdtree

snipemate.vim 代码片断伴侣

主页:https://github.com/msanders/snipmate.vim

实现打几个字符按一下tab自动生成一段格式好的代码的功能,比如 func 生成 function() {} 之类的。具体片断跟语法插件有关,不再细表

git clone git://github.com/msanders/snipmate.vim.git ~/.vim/bundle/snipmate.vim

syntastic 语法错误定位

主页:https://github.com/scrooloose/syntastic

在出错行的行号列显示高亮提示,方便定位出错的行。

git clone https://github.com/scrooloose/syntastic.git ~/.vim/bundle/syntastic

vim-javascript javascript语法插件

主页:https://github.com/pangloss/vim-javascript

基本的javascript语法插件,目前还有在更新

git clone https://github.com/pangloss/vim-javascript.git ~/.vim/bundle/vim-javascript

vim-es6 ES6语法高亮及代码片断

主页:https://github.com/isRuslan/vim-es6

除了语法高亮,还提供了几个 es6 特有的代码片断。

git clone https://github.com/isRuslan/vim-es6.git

eslint

主页:http://eslint.org/

安装:

npm i eslint -g

配置文件: ~/.eslintrc

` { “parser”: “babel-eslint”, “env”: { “es6”: true, “mocha”: true }, “plugins”: [ “react”, “json” ], “ecmaFeatures”: { “jsx”: true, “modules”: true

}, “rules”: { “semi”: 2 } } `

安装 Unite 文件搜索快速打开

这是一个牛逼的插件,可以通过关键字快速打开切换不同的文件。配合 pt (the_platinum_searcher) 可以实现文件夹级别的搜索

首先需要安装 vimproc.vim 让 vim 可以支持异步操作,这个 clone 之后还要编译一下:

git clone https://github.com/Shougo/vimproc.vim.git ~/.vim/bundle/vimproc.vim cd ~/.vim/bundle/vimproc.vim make

然后安装 pt, 具体步骤查看: https://github.com/monochromegane/the_platinum_searcher

最后安装 Unite:

git clone https://github.com/Shougo/unite.vim.git ~/.vim/bundle/unite.vim

安装 tern_for_vim js 自动完成

  1. 安装 tern_for_vim

git clone https://github.com/ternjs/tern_for_vim.git ~/.vim/bundle/tern_for_vim

  1. 安装 ternjs

全局安装:npm i tern -g 或者在 tern_for_vim 里面执行 npm i 也可以

配置 .vimrc/.gvimrc

.vimrc

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
" 启用 pathogen 插件管理
execute pathogen#infect()

" 开启语法着色
syntax on

" 开启文件类型
filetype plugin indent on

" 一个 tab 等于 2 个空格的宽度
set ts=2
set sw=2

" 按 tab 插入对应数量的空格
set expandtab

" 显示行号
set number

" 切换 NERDTree
map <C-t> :NERDTreeToggle<CR>

" 自动缩进
set autoindent

" 允许未保存的情况下打开新的文件或切换 buffer
set hidden

" 退出时若 session 中含有未保存的 buffer 提示保存
set confirm

" 设定自动关闭标签的有效文件扩展名
let g:closetag_filenames = "*.html,*.xhtml,*.phtml,*.js"

" 重复粘贴时按 \p 即可
vnoremap <leader>p "_dP

" 设定 javascript 的语法检测使用 eslint
let g:syntastic_javascript_checkers = ['eslint']

" 设定 jsx 着色对非 jsx 的文件也有效,如 js 文件
let g:jsx_ext_required = 0

"高亮多作的行尾空格
" 1. 新建一个高亮组
highlight ExtraWhitespace ctermbg=red guibg=red
" 2. 匹配行尾空格
match ExtraWhitespace /\s\+$/

" 配置 Unite 使用 pt 搜索
if executable('pt')
let g:unite_source_grep_command = 'pt'
let g:unite_source_grep_default_opts = '--nogroup --nocolor'
let g:unite_source_grep_recursive_opt = ''
let g:unite_source_grep_encoding = 'utf-8'
endif

function! ProjectOpen()
execute ':Unite -no-split file:' . ProjectRootGuess()
endfunction

function! ProjectGrep()
execute ':Unite -no-split grep:' . ProjectRootGuess()
endfunction

" 对 pwd 进行正则搜索
nnoremap <silent> <Leader>g :<C-u>call ProjectGrep()<CR>

" 打开文件 file
nnoremap <silent> <Leader>f :<C-u>call ProjectOpen()<CR>

" 打开文件 file_rec
nnoremap <silent> <Leader>c :<C-u>Unite -no-split file:.<CR>

" 打开 Unite 结果窗口
nnoremap <silent> <Leader><Space> :<C-u>UniteResume -no-split<CR>

" 快速切换窗口
nnoremap <silent> <Leader>w <C-w><C-w>

" 允许 Unite 删除文件
call unite#custom#alias('file', 'delete', 'vimfiler__delete')

" 自动将 pwd 切换到当前文件
set autochdir

" 将 shell 执行结果放到新开的 Scratch buffer。 使用方法: Shell eslint ./
command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand(<q-args>)
function! s:RunShellCommand(cmdline)
let isfirst = 1
let words = []
for word in split(a:cmdline)
if isfirst
let isfirst = 0 " don't change first word (shell command)
else
if word[0] =~ '\v[%#<]'
let word = expand(word)
endif
let word = shellescape(word, 1)
endif
call add(words, word)
endfor
let expanded_cmdline = join(words)
botright new
setlocal buftype=nofile nobuflisted noswapfile nowrap
call setline(1, 'You entered: ' . a:cmdline)
call setline(2, 'Expanded to: ' . expanded_cmdline)
call append(line('$'), substitute(getline(2), '.', '=', 'g'))
silent execute '$read !'. expanded_cmdline
1
endfunction

" 命令别名
ca shell Shell

" 关闭临时文件
set noswapfile

.gvimrc

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
" 高度 50 行
set lines=999

" 亮度 140 列
set columns=999

" 颜色主题
colo solarized

" 背影黑色
set background=dark

" 字体
set guifont=Monaco:h13

" 隐藏菜单栏
set guioptions-=m

" 自动开启 NERDTree
"NERDTreeToggle

" 设定 NERDTree 根目录
"NERDTree ~/Projects

" 默认目录
cd ~/Projects

if has("gui_macvim")
" Press Ctrl-Tab to switch between open tabs (like browser tabs) to
" the right side. Ctrl-Shift-Tab goes the other way.
noremap <C-Tab> :tabnext<CR>
noremap <C-S-Tab> :tabprev<CR>

" Switch to specific tab numbers with Command-number
noremap <D-1> :tabn 1<CR>
noremap <D-2> :tabn 2<CR>
noremap <D-3> :tabn 3<CR>
noremap <D-4> :tabn 4<CR>
noremap <D-5> :tabn 5<CR>
noremap <D-6> :tabn 6<CR>
noremap <D-7> :tabn 7<CR>
noremap <D-8> :tabn 8<CR>
noremap <D-9> :tabn 9<CR>
" Command-0 goes to the last tab
noremap <D-0> :tablast<CR>
endif

Share Comments

node.js 4.0 新特性

node.js 4.0 是 node.js 与 io.js 回归统一之后正式推出的第一个版本。这说明从此以后, node.js 将采用 io.js 的理念,积极跟进 v8 引擎的更新,支持各种各样的ES6新特性而不必加上 harmony 标签。测试稳定后的新特性将会成为 node.js 的一等公民。新特性未来将分成三种组别,分别是:交付、展示、进行中。分别是稳定版和公测版以及测试版的意思。

 

目前发布的 4.0 测试版有以下稳定特性:

Block scoping 块级作用域

块是指由显式或隐式{}包含起来的代码,比如 if (…) {} for (…) {} 括起来的部分即为块。在以往的标准中块是没有独立的作用域的,而是与函数体共享一个作用域。在作异步编程中有时会制造一些麻烦。ES6带来的块级作用域便是用来解决这一类的问题。

let

let 和 var 一样,是用来声明变量的,不同的时,var 是作用于函数体,而 let 则是作用于块级。请看代码:

for (var i = 0; i < 10; i++) {
  process.nextTick(function(){
    console.log(i);
  });
}
也许你会以为上面的代码会输出0到9,事实上这个只会输出10个9。因为 js 是按块级去执行代码,上面其实是先把循环0到9执行完了,再去一个个执行 nextTick 传入的函数。而每个函数引用的都是局部变量i,而这个时候i已经是9,自然就输出10个9了。 而let这个时候把 var 换成 let ,你会发现程序可以正确地输出 0~9 了,let 声明的是块级变量。也就是说每个 process.nextTick 会引用于属于它自己的 i ,而不是引用到同一个局部变量,如此一来程序便可以正确输出。 #### const const 关键字就好理解了,毕竟各种语言都有。js 一向缺少定义常量的功能,const 就是用来定义常量的。需要注意的是如果 const 定义的是一个 Array 或 Object 这样类型的变量,那变量的本身内容是可能被修改的:
const FOOBAR = { "foo": 1, "bar": 2 };
FOOBAR.foo = 3; // this is legal.
FOOBAR = { "foo": 3, "bar": 4}; // this is illegal.

function-in-block

这个应该块级函数作用域方面的特性,没有找到太多资料。目测应该与 let 是一类的意思。根据说明文档,这个东西目前还不是按ES6标准实现。未来可能会发生变化。

Class 类 (仅严格模式可用)

这个是比较重量级的新特性了,OO编程的基本元素。虽说一直以来有 prototype 这样的东西可以实现相似的功能,但定义起来毕竟别扭,虽然有很多类库帮助方便的定义类,但这样也造成各种不统一。参考起别人的代码总要费些劲。

<span class="token keyword">class</span> Square<span class="token class-name"> extends Polygon</span> <span class="token punctuation">{</span>
  <span class="token function">constructor<span class="token punctuation">(</span></span>height<span class="token punctuation">,</span> width<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>height <span class="token operator">=</span> height<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>width <span class="token operator">=</span> width<span class="token punctuation">;
</span>    super.name = 'Square';
  <span class="token punctuation">}

</span>  get area() {
    return this.height * this.width;
  }

  static areaEqual(a, b) {
    return a.area == b.area;
  }
<span class="token punctuation">}</span>`</pre>
很好,构造函数、属性、静态函数都有了,也不用写那么多 function ,这样定义一个类可要比以往写少很多代码了。结构明显清晰多了。

### Collection 集合

#### Map 字典

基本上这是跟 Object 很类似的类型,在 ES6 出现以前我们一向是把 Object 当作字典来使用的。那么 Map 与 Object 相比有哪些优势?我们为什么要用 Map 而不是 Object:
  • Object 是有 prototype 的,也就是说在遍历的时候要特别处理,否则 prototype 的条目也会被包含进来。当然,用 Object.create(null) 也可以避免这个问题。
  • Object 只接受 String 类型作为键(KEY),而 Map 可以接受任意类型的变量作为键,这跟Java/.NET 的字典类型行为一致。
  • Map 内部有维护一个条目数量 size ,随时可以通过 size 属性来知道字典里面条目的数量,跟Array的length差不多。而 Object 则是没有这样的东东的,只能手动一个个地算。
  • 虽然目前 Object 实际上是有序的,但根据标准,Object 并不保证 key 的有序性。而 Map 规定是有序的,按插入顺序排列。

    WeakMap 弱字典

    这个跟 Map 是类似的东西,但它的键是弱引用。在 Map 中由于键是强引用,它会阻止垃圾回收系统对键和值进行回收。弱引用的在于它不会阻止垃圾回收对键值进行删除,当程序其它引用该键的变量解除引用后,GC便会进行回收,相应的,WeakMap 中的键值对也会被删除。因为受到垃圾回收的影响,所以 WeakMap 是无法对键值进行遍历。这个貌似可以用来做缓存系统?

    Set 唯一集合

    跟数组类似,不同的是 Set 针对相同的值只存储一个,另外的区别就是不能下标引用。以往在没有 Set 的情况下只能用 Object 的 Key 来代替,有了这个,在内存占用上会更有优势,另外还有 length 的属性可供使用,方便多了。

    WeakSet 弱引用唯一集合

    这个原理上跟 WeakMap 是一样的,只不过 Map 变成了 Set

    TypedArray 强类型数姐

    如果你接触的语言够多,会发现,弱类型语言的数组和强类型的数组是很不一样的。一般的强类型语言,数组Array是长度不变的(当然类型也是固定的),而弱类型数组更像是强类型中的 List 或者 LinkList ,长度可变,可以存储任意类型的数组。随着 js 在 web Server端的崛起,人们开始需要直接通过 js 操作二进制原始数组,而 TypedArray 就是对应这个需求出现的特性。

    需要注意的是,在使用 Array.isArray 对 TypedArray 进行判断时是会返回 false 的。也就是它在本质上并非是 Array 。

    在架构上,TypedArray 分为两种层,底层是 ArrayBuffer 类型,这是一种纯粹的二进制数据,没有格式,无法直接进行操作。要对原始数据进行操作,需要通过 View 层进行,分别是 Int8Array、Uint8Array、Int16Array、Uint16Array 等类型。

    `var buffer = new ArrayBuffer(16);
    `
    `if (buffer.byteLength === 16) {
      console.log("Yes, it's 16 bytes.");
    } else {
      console.log("Oh no, it's the wrong size!");
    }
    `
    `var int32View = new Int32Array(buffer);`

    Generator 生成器

    通过 function 关键字,可以定义一个返回 Generator 的函数。Generator 某程度上跟 c# 的迭代器很相似。Generator 类似于 c# 中实现了 IEnumerable 的类。function 返回的实际上是一个 Generator 实例,这个 Generator 在 yield 的地方会将值返回给调用方,然后再继续执行后面的指令。

    `function* anotherGenerator(i) {
      yield i + 1;
      yield i + 2;
      yield i + 3;
    }
    
    function* generator(i){
      yield i;
      yield* anotherGenerator(i);
      yield i + 10;
    }
    
    var gen = generator(10);
    
    console.log(gen.next().value); // 10
    console.log(gen.next().value); // 11
    console.log(gen.next().value); // 12
    console.log(gen.next().value); // 13
    console.log(gen.next().value); // 20`
    整个 Koa.js 都是基于生成器作为中间件链接动作,说明这个特性也是重量级的特性,将来应用必然会很广。 #### Binary & Octal literal 二进制和八进制字面量
    0777 // 前面加零即为定义八进制字面量,若数字中有超过8的则视为定义十六进制字面量
    0o777 // 前面加0o即为定义八进制字段量
    0b00001111 // 前面加0b即为定义二进制字面量
    0xA0A0A0 // 前面加0x即为定义十六进制字面量

    Extended Object literal 扩展对象字面量

    这是对 Object 实便声明的一种扩展,说起来挺复杂,不如直接看代码:

    var obj = {
        // 指定 prototype
        __proto__: theProtoObj,
        // ‘handler: handler’ 简化声明方式
        handler,
        // 'toString: function()' 的简化声明方式
        toString() {
         // Super calls
         return "d " + super.toString();
        },
        // 动态属性名
        [ 'prop_' + (() => 42)() ]: 42
    };
    那么,没错,就是这么吊! #### Promises 承诺对象 那么,也就是说 bluebird 可以退休了?也好!棒子的英语水平太牛逼了,看他们的文档实在是折磨人! #### New String methods 新增的 String 方法 代替了一部份 lodash 的功能,[详情请戳这里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_6_support_in_Mozilla#Additions_to_the_String_object) #### Symbol 符号 这玩意大概是从 ruby 移植过来的概念,代表唯一且不可变的标识!嗯,太抽象了,说实话一直不太喜欢 ruby 的这种设定。有什么特别实用的地方吗?看 mozilla 的文档,貌似可以用来将一些信息隐式存储到 Object 实例中。因为 for in 和 Object.getOwnPropertyNames 都不会返回 Symbol 类型的键。由于唯一性,new Symbol('foo') != new Symbol('foo'),[详情还是戳这里](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol),大家发现有什么应用的地方可以参详一下。 #### Template String 模板字符串 来自 Perl、Shell Script、PHP的精华!通过反引号``介单,可以跨行,支持变量自动替换。很实用的新特性。 ES5代码:
    `var a = 5;
    var b = 10;
    console.log("Fifteen is " + (a + b) + " and\nnot " + (2 * a + b) + ".");
    // "Fifteen is 15 and
    // not 20."`

    ES6代码:

    <span class="token keyword">var</span> a <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">; </span>var b = 10;
    console<span class="token punctuation">.</span><span class="token function">log<span class="token punctuation">(</span></span>Fifteen is ${a + b} and
    not ${2 * a + b}.<span class="token punctuation">)</span><span class="token punctuation">;</span>

    可以看到代码量又显著减少了。各种喜闻乐见啊有木有。

    Arrow Function 箭头函数

    可以说这个是我个人最喜欢的新特性了,能少打几个字不说,代码看起来也更简练直观!

    `var a = [
    “Hydrogen”,
    “Helium”,
    “Lithium”,
    “Beryl­lium”
    ];

    var a2 = a.map(function(s){ return s.length }); //es5
    var a3 = a.map( s => s.length ); // es6

这个特性必须给五星好评。

##

Share Comments

Kenny 跆拳道考级

Share Comments

php-fpm / nginx 修改上传文件限制

一般情况下,新装的phpServer默认的上传大小限制在2m的样子。如果需要上传较大的文件,如视频时将会完全不够用。对于采用 nginx + php-fpm 的布署方式,需要分别修改反向代理服务nginx和php.ini两个软件实现上传限制调整。比如要将上传大小调整至500m

php-fpm

配置文件在 /etc/php5/fpm/php.ini 中,需要修改2项:

  • post_max_size 500m
  • upload_max_filesize 500m
    upload_max_filesize 用于限定单一文件的大小,每个被上传的文件不能超过这个值,post_max_size 用于限定同时上传的文件大小总和,限定多文件上传时总的文件大小。

配置完成后,执行下面的命令重启 php-fpm

service php5-fpm restart

ps: 不要用 /etc/init.d/php5-fpm restart 命令,这个无法正常重启。完成后刷新 wordpress 可以看到上传限制就会变成 500m (post_max_size和upload_max_filesize的最小值)

完成php-fpm设定之后还需要调整 nginx 的限制,否则数据还未传到 php 之前就会被 nginx block 掉。

nginx

配置 server 节增加或修改 client_max_body_size 为 500m 然后 service nginx restart 即可。

 

Share Comments

儿子的作文

IMG_20150429_203523

Share Comments

在Nodejs中贯彻单元测试 - CNode

Source: 在Nodejs中贯彻单元测试 - CNode

 





在团队合作中,你写好了一个函数,供队友使用,跑去跟你的队友说,你传个A值进去,他就会返回B结果了。过了一会,你队友跑过来说,我传个A值却返回C结果,怎么回事?你丫的有没有测试过啊?

大家一起写个项目,难免会有我要写的函数里面依赖别人的函数,但是这个函数到底值不值得信赖?单元测试是衡量代码质量的一重要标准,纵观Github的受欢迎项目,都是有test文件夹,并且buliding-pass的。如果你也为社区贡献过module,想更多人使用的话,加上单元测试吧,让你的module值得别人信赖。

要在Nodejs中写单元测试的话,你需要知道用什么测试框架,怎么测试异步函数,怎么测试私有方法,怎么模拟测试环境,怎么测试依赖HTTP协议的web应用,需要了解TDD和BDD,还有需要提供测试的覆盖率。
> 本文的示例代码会备份到 Github : unittest-demo

## 目录

1. 测试框架
2. 断言库
3. 需求变更
4. 异步测试
5. 异常测试
6. 测试私有方法
7. 测试Web应用
8. 覆盖率
9. 使用Makefile把测试串起来
10. 持续集成,Travis-cli
11. 一些观点
12. 彩蛋
13. 整理

## 测试框架

Nodejs的测试框架还用说?大家都在用,Mocha。

Mocha 是一个功能丰富的Javascript测试框架,它能运行在Node.js和浏览器中,支持BDDTDDQUnitExports式的测试,本文主要示例是使用更接近与思考方式的BDD,如果了解更多可以访问Mocha的官网

#### 

#### 测试接口

Mocha的BDD接口有:

describe() it()
before() after()
beforeEach() afterEach()

#### 安装

npm install mocha -g

#### 编写一个稳定可靠的模块

模块具备limit方法,输入一个数值,小于0的时候返回0,其余正常返回

exports.limit = function (num) {
if (num < 0) {
return 0;
}
return num;
};</pre> #### 目录分配 *lib,存放模块代码的地方 *test,存放单元测试代码的地方 *index.js,向外导出模块的地方 *package.json,包描述文件 #### 测试 <pre class="prettyprint language-javascript">var lib = require(‘index’);

describe
(‘module’, function () {
describe
(‘limit’, function () {
it
(‘limit should success’, function () {
lib
.limit(10);
});
});
});</pre> #### 结果 在当前目录下执行mocha: <pre class="prettyprint">$ mocha



1 test complete (2ms)</pre> ## 断言库 上面的代码只是运行了代码,并没有对结果进行检查,这时候就要用到断言库了,Node.js中常用的断言库有: * should.js * expect.js * chai #### 加上断言 使用should库为测试用例加上断言 <pre class="prettyprint language-javascript">it(‘limit should success’, function () {
lib
.limit(10).should.be.equal(10);
});</pre> ## 需求变更 需求变更啦:limit这个方法还要求返回值大于100时返回100。 针对需求重构代码之后,正是测试用例的价值所在了, 它能确保你的改动对原有成果没有造成破坏。 但是,你要多做的一些工作的是,需要为新的需求编写新的测试代码。 ## 异步测试 #### 测试异步回调 lib库中新增async函数: <pre class="prettyprint language-javascript">exports.async = function (callback) {
setTimeout
(function () {
callback
(10);
}, 10);
}; </pre> 测试异步代码: <pre class="prettyprint language-javascript">describe(‘async’, function () {
it
(‘async’, function (done) {
lib
.async(function (result) {
done();
});
});
});</pre> #### 测试Promise 使用should提供的Promise断言接口: *finally|eventually*fulfilled*fulfilledWith*rejected*rejectedWith*then测试代码 <pre class="prettyprint language-javascript">describe(‘should’, function () {
describe
(‘#Promise’, function () {
it
(‘should.reject’, function () {
(new Promise(function (resolve, reject) {
reject
(new Error(‘wrong’));
})).should.be.rejectedWith(‘wrong’);
});

it
(‘should.fulfilled’, function () {
(new Promise(function (resolve, reject) {
resolve
({username: ‘jc’, age: 18, gender: ‘male’})
})).should.be.fulfilled().then(function (it) {
it
.should.have.property(‘username’, ‘jc’);
})
});
});
});</pre> #### 异步方法的超时支持 Mocha的超时设定默认是2s,如果执行的测试超过2s的话,就会报timeout错误。 可以主动修改超时时间,有两种方法。 #### 命令行式mocha -t 10000#### API式 <pre class="prettyprint language-javascript">describe(‘async’, function () {
this.timeout(10000);
it
(‘async’, function (done) {
lib
.async(function (result) {
done();
});
});
});</pre> 这样的话async执行时间不超过10s,就不会报错timeout错误了。 ## 异常测试 异常应该怎么测试,现在有getContent方法,他会读取指定文件的内容,但是不一定会成功,会抛出异常。 <pre class="prettyprint language-javascript">exports.getContent = function (filename, callback) {
fs
.readFile(filename, ‘utf-8’, callback);
};</pre> 这时候就应该模拟(mock)错误环境了 #### 简单Mock <pre class="prettyprint language-javascript">describe(“getContent”, function () {
var _readFile;
before
(function () {
_readFile
= fs.readFile;
fs
.readFile = function (filename, encoding, callback) {
process
.nextTick(function () {
callback
(new Error(“mock readFile error”));
});
};
});
// it();
after
(function () {
// 用完之后记得还原。否则影响其他case
fs
.readFile = _readFile;
})
});</pre> #### Mock库 Mock小模块:[muk](https://github.com/fent/node-muk) ,略微优美的写法: <pre class="prettyprint language-javascript">var fs = require(‘fs’);
var muk = require(‘muk’);

before
(function () {
muk
(fs, ‘readFile’, function(path, encoding, callback) {
process
.nextTick(function () {
callback
(new Error(“mock readFile error”));
});
});
});
// it();
after
(function () {
muk
.restore();
});</pre> ## 测试私有方法 针对一些内部的方法,没有通过exports暴露出来,怎么测试它? <pre class="prettyprint language-javascript">function _adding(num1, num2) {
return num1 + num2;
}</pre> #### 通过rewire导出方法 模块:[rewire](http://jhnns.github.com/rewire/) <pre class="prettyprint">it(‘limit should return success’, function () {
var lib = rewire(‘../lib/index.js’);
var litmit = lib.get(‘limit’);
litmit
(10);
});</pre> ## 测试Web应用 在ProgrammingWeb项目的时候,要测试某一个API,如:/user,到底怎么编写测试用例呢? 使用:[supertest](https://github.com/visionmedia/supertest) <pre class="prettyprint language-javascript">var express = require(“express”);
var request = require(“supertest”);
var app = express();

// 定义路由
app
.get(‘/user’, function(req, res){
res
.send(200, { name: ‘jerryc’ });
});

describe
(‘GET /user’, function(){
it
(‘respond with json’, function(done){
request
(app)
.get(‘/user’)
.set(‘Accept’, ‘application/json’)
.expect(‘Content-Type’, /json/)
.expect(200)
.end(function (err, res) {
if (err){
done(err);
}
res
.body.name.should.be.eql(‘jerryc’);
done();
})
});
});</pre> ## 覆盖率 测试的时候,我们常常关心,是否所有代码都测试到了。 这个指标就叫做[“代码覆盖率”](http://en.wikipedia.org/wiki/Code_coverage)(code coverage)。它有四个测量维度。 > * **行覆盖率**(line coverage):是否每一行都执行了? > * **函数覆盖率**(function coverage):是否每个函数都调用了? > * **分支覆盖率**(branch coverage):是否每个if代码块都执行了? > * **语句覆盖率**(statement coverage):是否每个语句都执行了? [Istanbul](https://github.com/gotwarlost/istanbul) 是 JavaScript 程序的代码覆盖率工具。 #### 安装$ npm install -g istanbul#### 覆盖率测试 在编写过以上的测试用例之后,执行命令:istanbul cover _mocha就能得到覆盖率: <pre class="prettyprint language-javascript">JerryC% istanbul cover _mocha

module
limit
limit should success
async
async
getContent
getContent
add
add

should
#Promise
should.reject
should fulfilled

6 passing (32ms)

================== Coverage summary ======================
Statements : 100% ( 10/10 )
Branches : 100% ( 2/2 )
Functions : 100% ( 5/5 )
Lines : 100% ( 10/10 )
==========================================================</pre> 这条命令同时还生成了一个 coverage 子目录,其中的 coverage.json 文件包含覆盖率的原始数据,coverage/lcov-report 是可以在浏览器打开的覆盖率报告,其中有详细信息,到底哪些代码没有覆盖到。 ![覆盖率html](http://kleshwong.com/uploads/2015/07/eac87dbf-4e4b-426e-80ac-7c50e1b9a1cb.jpg) 上面命令中,istanbul cover命令后面跟的是_mocha命令,前面的下划线是不能省略的。 因为,[mocha 和 _mocha 是两个不同的命令](https://github.com/gotwarlost/istanbul/issues/44),前者会新建一个进程执行测试,而后者是在当前进程(即 istanbul 所在的进程)执行测试,只有这样, istanbul 才会捕捉到覆盖率数据。其他测试框架也是如此,必须在同一个进程执行测试。 如果要向 mocha 传入参数,可以写成下面的样子。 <pre class="prettyprint">$ istanbul cover _mocha tests/test.sqrt.js -R spec</pre> 上面命令中,两根连词线后面的部分,都会被当作参数传入 Mocha 。如果不加那两根连词线,它们就会被当作 istanbul 的参数(参考链接[1](http://www.clock.co.uk/blog/npm-module-code-coverage-in-2-simple-steps),[2](http://www.vapidspace.com/coding/2014/10/29/code-coverage-metrics-with-mocha-and-istanbul/))。 ## 使用Makefile串起项目 <pre class="prettyprint">TESTS = test/.test.js
REPORTER = spec
TIMEOUT = 10000
JSCOVERAGE = ./node_modules/jscover/bin/jscover

test:
@NODE_ENV=test ./node_modules/mocha/bin/mocha -R $(REPORTER) -t $(TIMEOUT) $(TESTS)

test-cov: lib-cov
@LIB_COV=1 $(MAKE) test REPORTER=dot
@LIB_COV=1 $(MAKE) test REPORTER=html-cov > coverage.html

lib-cov:
@rm -rf ./lib-cov
@$(JSCOVERAGE) lib lib-cov

.PHONY: test test-cov lib-cov

make test
make test-cov
`
用项目自身的jscover和mocha,避免版本冲突和混乱

## 持续集成,Travis-cli Travis-ci

绑定Github帐号 在Github仓库的Admin打开Services hook
打开Travis 每次push将会hook触发执行npm test命令
注意:Travis会将未描述的项目当作Ruby项目。所以需要在根目录下加入.travis.yml文件。内容如下:
<span class="pln">language</span><span class="pun">:</span><span class="pln"> node_js
    node_js</span><span class="pun">:</span>
      <span class="pun">-</span> <span class="str">"0.12"</span>

Travis-cli还会对项目颁发标签,

![/](https://camo.githubusercontent.com/f479d6cf4ac300093da5a90d70565cebf8c8ed40/68747470733a2f2f7365637572652e7472617669732d63692e6f72672f4a61636b736f6e5469616e2f626167706970652e706e67)or ![/](https://camo.githubusercontent.com/08478cd5a732822aec47e6e60d5f823ef0898dec/68747470733a2f2f7365637572652e7472617669732d63692e6f72672f54424544502f64617461766a732e706e67)

如果项目通过所有测试,就会build-passing,

如果项目没有通过所有测试,就会build-failing

## 一些观点

实施单元测试的时候, 如果没有一份经过实践证明的详细规范, 很难掌握测试的 "度", 范围太小施展不开, 太大又侵犯 “别人的” 地盘. 上帝的归上帝, 凯撒的归凯撒, 给单元测试念念紧箍咒不见得是件坏事, 反而更有利于发挥单元测试的威力, 为代码重构和提高代码质量提供动力.

这份文档来自 Geotechnical, 是一份非常难得的经验准则. 你完全可以以这份准则作为模板, 结合所在团队的经验, 整理出一份内部单元测试准则.

[单元测试准则](https://github.com/yangyubo/zh-unit-testing-guidelines)

## 彩蛋

最后,介绍一个库:[faker`](https://github.com/Marak/Faker.js)

他是一个能伪造用户数据的库,包括用户常包含的属性:个人信息、头像、地址等等。

是一个Programming初期,模拟用户数据的绝佳好库。

支持Node.js和浏览器端。

生成用户

## 整理

#### Nodejs的单元测试工具

1. 测试框架 mocha
2. 断言库:should.js、expect.js、chai
3. 覆盖率:istanbul、jscover、blanket
4. Mock库:muk
5. 测试私有方法:rewire
6. Web测试:supertest
7. 持续集成:Travis-cli

## 参考

https://github.com/JacksonTian/unittesting http://html5ify.com/unittesting/slides/index.html
http://www.ruanyifeng.com/blog/2015/06/istanbul.html http://coolshell.cn/articles/8209.html
http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests https://github.com/yangyubo/zh-unit-testing-guidelines
http://www.codedata.com.tw/java/unit-test-the-way-changes-my-programming http://wiki.ubuntu.org.cn/%E8%B7%9F%E6%88%91%E4%B8%80%E8%B5%B7%E5%86%99Makefile:MakeFile%E4%BB%8B%E7%BB%8D
https://github.com/yangyubo/zh-unit-testing-guidelines https://github.com/visionmedia/superagent/blob/master/Makefile


Share Comments

快速上手Promise

这里,我不打算讲Promise的原理,以及回调地狱 blah, blah, blah… 之类。这样的文章网上实在太多了,google 一下一地都是。
但是,讲究竟如何实际去运用的却很少,使用上细节其实很重要。这也是很多人搞不明白这玩意怎么用的原因所在。这里我们以 bluebird 为例看下 Promise 是啥玩意。

首先,Promise它长啥样?

简单来讲,它就是一种把回调转换成链接操作的编程方法。那么什么是链式?jQuery大家都会比较熟悉吧。看下下面这段代码:

$('div').css('highlight').html('Hello world').show();
`</pre>

这就是链式操作。那么,这个链式操作是怎么完成的呢?稍微看下 jQuery 的代码或者写过 jQuery 扩展的人都知道,它是通过在每个 function 体最后返回一个 jQuery 对象完成的。在上面这段代码中,所有的调用之后其实都是一个 jQuery 对象。所有的 css,html, show 都是由 jQuery 对象提供的方法。

## jQuery和Promise有什么关系?

jQuery 是链式操作的老祖宗,是不是原创的我不敢说,但是 jQuery 把这种风格推广到整个技术界这点是勿用置疑的。本质上 Promise 也是对这链式操作思想的发扬光大。链式操作的优势是很明显的,对比 jQuery 和以往传统的 javascript 可以明显地看到代码可读性不在一个层级上。我们先看下正常情况下如何读取文件:

<pre>`fs.readFile('file.txt', "utf-8", function (err, data) {
  if (err) return console.error(err);
  console.log(data);
});
`</pre>

很常见的。Promise 完成同样的功能是怎么写呢?首先,要初始化生成 promisified function.

<pre>`var Promise = require('bluebird');
var readAsync = Promise.promisify(fs.readFile);
var readFile = function(path) {
  return readAsync(path, 'utf-8');
}
`</pre>

然后是使用:

<pre>`readFile('/etc/passwd').then(console.log).catch(console.error);
`</pre>

风格上是不是跟 jQuery 很像?但是好像除了短一点,其它好处不明显呐?

<pre>`fs.readFile('file.txt', 'utf-8', function (err1, data1) {
  if (err1) return console.error(err1);
  fs.readFile(data1, 'utf-8', function(err2, data2) {
    if (err2) return console.error(err2);
    console.log(data2);
  }
});
`</pre>

<pre>`readFile('file.txt').then(readFile).then(console.log).catch(console.error);
`</pre>

结果是一样的,可读性不在一个层次上。并且,万一哪个回调中忘了写上 if(err) 这样的判断或者是忘了写 return ,除起错了可不好玩!你会不会写错我不知道,反正我不敢保证我一定不会写错!

## 上面的代码是怎么回事?

这里,我们确定几个术语:
  1. Promise是一种编程方法(思想),哲学上的概念。
  2. bluebird 是对 Promise 的一种实现。
  3. readFile 是 Promisified Function,它会返加一个 Promise对象。一个 Promise对象就是对一个异步任务的包装,它会产生两种结果:resolved代表成功执行下一个 then, rejected代表失败执行 catch。
  4. Promise 对象最主要就是提供了 then 方法(catch、finally 都是特殊的 then)。then 是 Promise 的核心,所以 Promise 对象也称作 Thenable。
  5. then 方法接收一个 function 。在 Promisified Function 顺利完成之后执行这个 function 。出错则执行 catch 的 function

    关键的地方在于 then 是怎么运作的?理解 then 也就解决了问题的百分之六十。

  • then 接收一个 function 或一个 promise对象(这点要特别注意,后面有讲到一个示例会牵涉到这个关键点)* then 在异步任务完成后调用这个 function ,同时,会把异步操作的结果值传入,所以上面第一个 then 的 readFile 会接收到 file.txt 的内容。
  • then 不管你这个 function 里面返回什么东西,它对返回值只作一个判断:是不是 Promise对象
  • 是 Promise对象:把它插入当前链式操作中,后面的 then 会在这个 Promise对象 完成后继续。
  • 否 把这个返回值传入到下一个 then 中(当然,如果没有 return ,这个值就是 undefined)。
  • 若传入的是promise对象,则会等待该 promise对象执行完成,再继续执行当前的链,之前的结果会被继续传递

    总的来讲,then方法执行完毕后总是返回一个 Promise对象。结果是你可以一直 then 下去。。。
    好吧,then方法好像很牛逼的样子,那到底怎么牛逼法?

    `readFile('file.txt').then(function(data) {
      if (data == '')
        return readFile('file_init.txt').then(readFile); //是 Promise对象
      return data; //不是 Promise对象
    }).then(console.log).catch(console.error);`
    `

    牛逼的地方就在于我们可以动态的修改链式操作的走向。这样的代码看起来既舒服又简单,试一下用传统的方法写一下?

    刚才说的示例

    `doSomething().then(function () {
    return doSomethingElse();
    });

    doSomething().then(function () {
    doSomethingElse();
    });

    doSomething().then(doSomethingElse());

    doSomething().then(doSomethingElse);

这是下面四种 Promise 的用法有何差异?, ( 从 阮一峰微博里面挪过来的)。 中修正后的代码。
原文还提到:

doSomething & doSomethingElse both promise object

我想说:

No, they are not. They are promisified function. Function and Object are quite different things.

先别往下拉,请先看下上面四种方式,有什么不同?如果明白了,说明你已经基本掌握 Promise 了。

确认结论是否正确(修正)

  1. 脱裤子放屁,多了一层 function 包装,跟4是一样的效果。
  2. 它后面再加 then 是不会等到 doSomethinElse 完成后执行,而是同时进行。
  3. 传入的其实是一个 promise object,这个 promise object 会被执行并等待其完成,但结果会被忽略,第三个 then 接收到的仍是第一个 readFile 的结果。
  4. doSomethingElse 本身就是个 function,传入后会被调用,返回一个 Promise对象 ( doSomethingElse 不是 promise object, 它的返回值才是 promise object)。

当然,看不出来也说明不了什么问题,因为这样的示例迷惑性很强,给出的提示也不明显。正常情况下更不会存在这样的代码。顺便一提,这也是函数式语言的 side effect,很容易绕晕掉到坑里。根据 (We have a problem with promises)[http://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html]里面所讲,掉坑的人不在少数!

还需要知道其它的吗?

以上只是基础知识,实际应用时当然还有一些扩展的方法需要去了解,比如 spread, all 等。npmjs.org 上的文档那是必读的……

Share Comments