Oct 31, 2014

用 JavaScript 实现 ruby times 方法

  • JavaScript
  • ruby
  • times

JavaScript

Number.prototype.times = function(fn) {
  var times = this.valueOf();
  while(times && times > 0){
  	fn();
  	times--;
  }
};

5..times(function(){
  console.log('Hello World!');
});

CoffeeScript

Number::times = (fn) ->
  do fn for [1..@valueOf()] if @valueOf()
  return

5.times -> console.log 'Hello World!'
Oct 27, 2014

无法抹去的记忆

梦魇

很小年纪的时候就开始做的一个梦:我孤身站在一个高空的跳台上,跳台的弹力不断的把我弹上高空,然后落下来,接着把我再弹上高空… 一阵阵纠心反复循环,犹如飞机遇上不稳定的气流,人处于失重的状态,最后的结果都是我被纠结醒来。

直到现在偶尔还会做这个梦,找不到原因。

车祸

几月前的一天早晨,骑车去地铁站,经过一座桥下坡时,见一女子在路中间拍打一大众POLO的后背箱。再看车底,压着一个人!!! 我扔下单车,跑过去趴下来看,车底压着一个小男孩,被卷在了后轴处,我尝试去抬起车尾,力量不够。那时也有其他人参与过来,一起把车尾抬起。小孩被拉了出来。不忍直视,全身发红、都是擦伤、眼睛微开,无神…

围观的人已经报警,叫救护车,我转身离开,不忍再多看一眼。整个一天都在想着那个画面,小孩经历的过程太过痛苦!晚上回家再经过事发地,询问附近的住户,小孩伤势太重没能抢救过来。小孩8岁,父母来沪做早点生意。事发原因大概是小孩横穿马路(路口红绿灯大概只有10米不到),可能太突然司机来不及反应,先是将小孩撞飞倒地,然后再压过去…

接下来的一周时间一直会想起小孩被拉出来的那个画面,生命太脆弱,不能重来!后来小孩父母将店铺转让搬离了这个痛苦伤心的地方。

Oct 25, 2014

Installing Go on the Raspberry Pi

  • GO
  • Raspberry Pi

最近在看《GO语言程序设计》,另一个做嵌入式开发的小伙伴问我 Raspberry Pi 的问题,临时想到能不能在 Raspberry Pi 里搭一个 GO 的环境呢?之前在里面搭过 ruby 的环境,GO 这种静态语言效率应该会更高一点。

下载源码

Golang的文档上说是支持多平台的,其中也包括了ARM,下载页面:

http://code.google.com/p/go/downloads/list

没有找到 ARM 平台的二进制包下载。所以 ARM 平台下的需要下载源码自己编译。

下载源码,两种方式:一种是直接下载压缩包文件(推荐),另一种是 clone 源代码

hg clone -u default https://code.google.com/p/go /home/go

我一般会安装在 /usr/local 目录下。

安装依赖包

以编译安装前需要安装以下依赖包:mercurial gcc libc6-dev

sudo apt-get install -y mercurial gcc libc6-dev

编译

% cd /home/go/src
% ./all.bash

这是一个漫长的过程,大概花了近一个小时,安装成功后你会见到这些信息:

ALL TESTS PASSED

---
Installed Go for linux/arm in /home/go
Installed commands in /home/go/bin

配置GO的环境变量

export PATH=$PATH:$HOME/go/bin

测试:

go version
Oct 22, 2014

Glossary

  • Glossary

QPS 每秒查询率

QPS每秒查询率(Query Per Second)

每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准,在因特网上,作为域名系统服务器的机器的性能经常用每秒查询率来衡量。 对应fetches/sec,即每秒的响应请求数,也即是最大吞吐能力。

FPS 每秒传输帧数

FPS(Frames Per Second):每秒钟填充图像的帧数(帧/秒),FPS是测量用于保存、显示动态视频的信息数量,通俗来讲就是指动画或视频的画面数。在电影视频及数字视频上,每一帧都是静止的图象;快速连续地显示帧便形成了运动的假象。每秒钟帧数 (FPS) 愈多,所显示的动作就会愈流畅。

FPS也可以理解为我们常说的“刷新率(单位为Hz)”,常见媒体的FPS帧率:

电影:24fps
电视(PAL):25fps
电视(NTSL):30fps
CRT显示器:75Hz以上
液晶显示器:60Hz

QUIC

Quick UDP Internet Connections 谷歌对种UDP通信的改进版,快速UDP互联网连接,类似于SPDY,旨在减少网络延迟,目标是优化或替换那些需要使用面向链接的应用程序中所采用的TCP协议。

Oct 21, 2014

JavaScript Timer

  • JavaScript
  • setTimeout
  • setInterval
  • requestAnimationFrame
  • setImmediate

JavaScript 定时器

在 JavaScript 中说到定时器,最常用的就两个: setTimeout()setInterval() 这两个函数,它们的内部运行机制完全一样,区别在于 setTimeout 指定的代码是一次性执行,setInterval 则为反复执行。

setTimeout()

语法

var timerID = window.setTimeout(func/code, delay);
  • timerID 是该延时操作的数字ID, 此ID随后可以用来作为clearTimeout方法的参数.
  • func 是你想要在delay毫秒之后执行的函数,code 在第二种语法,是指你想要在delay毫秒之后执行的代码 (使用该语法是不推荐的, 不推荐的原因和eval()一样)
  • delay 是延迟的毫秒数 (一秒等于1000毫秒),函数的调用会在该延迟之后发生.但是实际的延迟时间可能会稍长一点.

例子

function test(text) {
	console.log("print: " + text);
}
setTimeout(test, 1000);
// 使用匿名函数来传递参数
function test(text) {
	console.log("print:" + text);
}
setTimeout(function(){
	test("Hello world!");
}, 1000);
// 不推荐的用法
setTimeout("test('Hello world!')", 1000);

在 setTimeout 的回调函数或匿名函数中要特别注意 this 的值在上下文中的变化。

delay 的延迟

如果将delay设为0,就表示当前代码执行完(执行栈清空)以后,立即执行(0毫秒间隔)指定的回调函数。

setTimeout(function(){console.log(1);}, 0);
console.log(2);

在早期,JavaScript 的 callback 执行,是依赖 CPU 的中断来进行控制的,如果两个中断之间时间太短会导致,CPU 性能消耗很高,同时影响能耗,于是微软和英特公司为了解决这个问题,就约定每个中断之间的间隔是 15.6ms(64 fps)所以就是我们常见的约等于 16ms 的间隔。

现在 HTML5 标准规定了 setTimeout() 的第二个参数的最小值(最短间隔),不得低于4毫秒,setTimeout的间隔缩短到了 4ms(250 fps)。

这个坑在我做 FFTS.IO 的时候被踩到,FFTS.IO 上传的效果需要用 canvas 做一个秒表,每秒钟需要去绘制一个圆,当时简单粗暴的这样写了:

setInterval(function(){
	ctx.arc(...)
},1)

每毫秒去绘制一个角度 (360/1000) 出来的效果总是要比实际时间长。于是将 delay 设置为 16,每次绘制角度 360/(1000/16) 这样才正常。当然也可以使用

requestAnimationFrame()

requestAnimationFrame()

requestAnimationFrame() 通常被调用的频率是每秒60次, 不仅仅可以解决中断调度的问题,还可以更加优化得统一管理动画单元里dom元素的repaint方式, 效果要好于setTimeout(), 但是 IE10 以下浏览器还不支持。

setImmediate()

该方法最近刚刚被微软提出, 可能不会被w3c批准成为标准, 目前只有 Internet Explorer 10实现了该方法. setImmediate大约0.16ms执行一次,fps超过6000。

参考链接

https://developer.mozilla.org/zh-CN/docs/DOM/window.setTimeout

https://developer.mozilla.org/zh-CN/docs/Web/API/Window.setInterval

https://developer.mozilla.org/zh-CN/docs/Web/API/window.requestAnimationFrame

https://developer.mozilla.org/zh-CN/docs/Web/API/window.setImmediate

Oct 19, 2014

FFTS.IO

  • FFTS.IO
  • Qiniu
  • Cloud Storage
  • File Transfer Station

FFTS.IO

http://ffts.io/

Fast File Transfer Station.

这是国庆在家闲得无聊做的一个文件中转站,利用七牛云存储双向加速,用户直接从客户端上传文件到七牛服务器,下载也是从七牛服务器分发。

文件中转站这个想法一个月之前就有了,编码大概只花了两个晚上的时间,因为功能比较简单,大部分时间都纠结在前端展示的效果上面。目前的效果直接利用 canvas 绘制动画。

代码已开源: https://github.com/miclle/FFTS

Oct 17, 2014

ui-router

  • AngularJS
  • ui-router

#AngularUI Router

AngularJS 不提供模板视图的嵌套功能,而 ui-router 很好的解决了这一问题。

获取ui-router

clone & build this repository download the release (or minified)
Bower: $ bower install angular-ui-router from your console
npm: $ npm install angular-ui-router from your console
Component: $ component install angular-ui/ui-router from your console

引用文件并添加到 module 中

<!doctype html>
<html ng-app="myApp">
<head>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script>
    <script src="js/angular-ui-router.min.js"></script>
    <script>
        var myApp = angular.module('myApp', ['ui.router']);
        // For Component users, it should look like this:
        // var myApp = angular.module('myApp', [require('angular-ui-router')]);
    </script>
    ...
</head>
<body>
    ...
</body>
</html>

使用 ui-view 指令替换原来的 ng-view

在 ui-router 中使用 state 来进行 route 的切换,在 a 标签上使用 ui-sref 并能链接指向相应的 state

<body>
  <div ui-view></div>
  <!-- We'll also add some navigation: -->
  <a ui-sref="state1">State 1</a>
  <a ui-sref="state2">State 2</a>
</body>
<!-- partials/state1.html -->
<h1>State 1</h1>
<!-- partials/state2.html -->
<h1>State 2</h1>

在 app config 中使用 $stateProvider 来配置需要的 state

myApp.config(function($stateProvider, $urlRouterProvider) {

  // For any unmatched url, redirect to /state1
  $urlRouterProvider.otherwise("/state1");
  //
  // Now set up the states
  $stateProvider
    .state('state1', {
      url: "/state1",
      templateUrl: "partials/state1.html"
    })
    .state('state2', {
      url: "/state2",
      templateUrl: "partials/state2.html"
    });
});

通过上面两步就可以实现与 angularjs $routeProvider 同样的功能,但在 ui-router 中还可以实现 view 和 state 的嵌套

<!-- partials/state1.html -->
<h1>State 1</h1>
<hr/>
<a ui-sref="state1.list">Show List</a>
<div ui-view></div>
<!-- partials/state2.html -->
<h1>State 2</h1>
<hr/>
<a ui-sref="state2.list">Show List</a>
<div ui-view></div>
<!-- partials/state1.list.html -->
<h3>List of State 1 Items</h3>
<ul>
  <li ng-repeat="item in items"></li>
</ul>
<!-- partials/state2.list.html -->
<h3>List of State 2 Things</h3>
<ul>
  <li ng-repeat="thing in things"></li>
</ul>
myApp.config(function($stateProvider, $urlRouterProvider) {
  //
  // For any unmatched url, redirect to /state1
  $urlRouterProvider.otherwise("/state1");
  //
  // Now set up the states
  $stateProvider
    .state('state1', {
      url: "/state1",
      templateUrl: "partials/state1.html"
    })
    .state('state1.list', {
      url: "/list",
      templateUrl: "partials/state1.list.html",
      controller: function($scope) {
        $scope.items = ["A", "List", "Of", "Items"];
      }
    })
    .state('state2', {
      url: "/state2",
      templateUrl: "partials/state2.html"
    })
    .state('state2.list', {
      url: "/list",
      templateUrl: "partials/state2.list.html",
      controller: function($scope) {
        $scope.things = ["A", "Set", "Of", "Things"];
      }
    });
});

上面的代码是一个简单的嵌套例子,在 $stateProvider 中配置的 state1.list 和 state2.list 都输出到 state1 和 state2 对应的视图 state1.html 和 state2.html 中的 ui-view 指令标签里

Sep 29, 2014

Cookie

  • Cookie

cookie 的属性

expires 属性

cookie的生存期,默认情况下cookie是暂时存在的,他们存储的值只在浏览器会话期间存在,当用户退出浏览器后这些值也会丢失,如果想让cookie存在一段时间,就要为expires属性设置为未来的一个用毫秒数表示的过期日期或时间点,expires默认为设置的expires的当前时间。现在已经被max-age属性所取代,max-age用秒来设置cookie的生存期。

如果max-age属性为正数,则表示该cookie会在max-age秒之后自动失效。浏览器会将max-age为正数的cookie持久化,即写到对应的cookie文件中。无论客户关闭了浏览器还是电脑,只要还在max-age秒之前,登录网站时该cookie仍然有效。

如果max-age为负数,则表示该cookie仅在本浏览器窗口以及本窗口打开的子窗口内有效,关闭窗口后该cookie即失效。max-age为负数的Cookie,为临时性cookie,不会被持久化,不会被写到cookie文件中。cookie信息保存在浏览器内存中,因此关闭浏览器该cookie就消失了。cookie默认的max-age值为-1。

‍如果max-age为0,则表示删除该cookie。cookie机制没有提供删除cookie的方法,因此通过设置该cookie即时失效实现删除cookie的效果。失效的Cookie会被浏览器从cookie文件或者内存中删除。

如果不设置expires或者max-age这个cookie默认是Session的,也就是关闭浏览器该cookie就消失了。

domain 属性

domain属性可以使多个web服务器共享cookie。domain属性的默认值是创建cookie的网页所在服务器的主机名。不能将一个cookie的域设置成服务器所在的域之外的域。

path 属性

它指定与cookie关联在一起的网页。在默认的情况下cookie会与创建它的网页,该网页处于同一目录下的网页以及与这个网页所在目录下的子目录下的网页关联

secure 属性

它是一个布尔值,指定在网络上如何传输cookie,默认是不安全的,通过一个普通的http连接传输

HttpOnly 属性

HttpOnly 属性限制了 cookie 对 HTTP 请求的作用范围。特别的,该属性指示用户代理忽略那些通过“非 HTTP” 方式对 cookie 的访问(比如浏览器暴露给js的接口)。注意 HttpOnly 属性和 Secure 属性相互独立:一个 cookie 既可以是 HttpOnly 的也可以有 Secure 属性。

cookie 的传输

浏览器将cookie信息以name-value对的形式存储于本地,每当请求新文档时,浏览器将发送Cookie,目的是让Server可以通过HTTP请求追踪客户。所以从WEB性能的角度来说我们要尽量的减小cookie,以达到传输性能的最大化。

cookie 的编码和解码

由于cookie的名/值中的值不允许包含分号,逗号和空格符,为了最大化用户代理和服务器的兼容性,任何被存储为 cookie 值的数据都应该被编码,例如用我们前端熟知的js全局函数encodeURIComponent编码和decodeURIComponent解码。

Sep 19, 2014

HTTP Header 详解

  • HTTP
  • Header

HTTP(HyperTextTransferProtocol)即超文本传输协议,目前网页传输的的通用协议。HTTP协议采用了请求/响应模型,浏览器或其他客户端发出请求,服务器给与响应。就整个网络资源传输而言,包括message-header和message-body两部分。首先传递message-header,即http header消息 。

http header 消息通常被分为4个部分:general header, request header, response header, entity header。根据维基百科对http header内容的组织形式,大体分为Request和Response两部分。

Requests 部分

Header解释示例
Accept 指定客户端能够接收的内容类型 Accept: text/plain, text/html
Accept-Charset 浏览器可以接受的字符编码集。 Accept-Charset: iso-8859-5
Accept-Encoding 指定浏览器可以支持的web服务器返回内容压缩编码类型。 Accept-Encoding: compress, gzip
Accept-Language 浏览器可接受的语言 Accept-Language: en,zh
Accept-Ranges 可以请求网页实体的一个或者多个子范围字段 Accept-Ranges: bytes
Authorization HTTP授权的授权证书 Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Cache-Control 指定请求和响应遵循的缓存机制 Cache-Control: no-cache
Connection 表示是否需要持久连接。(HTTP 1.1默认进行持久连接) Connection: close
Cookie HTTP请求发送时,会把保存在该请求域名下的所有cookie值一起发送给web服务器。 Cookie: $Version=1; Skin=new;
Content-Length 请求的内容长度 Content-Length: 348
Content-Type 请求的与实体对应的MIME信息 Content-Type: application/x-www-form-urlencoded
Date 请求发送的日期和时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
Expect 请求的特定的服务器行为 Expect: 100-continue
From 发出请求的用户的Email From: user@email.com
Host 指定请求的服务器的域名和端口号 Host: www.zcmhi.com
If-Match 只有请求内容与实体相匹配才有效 If-Match: “737060cd8c284d8af7ad3082f209582d”
If-Modified-Since 如果请求的部分在指定时间之后被修改则请求成功,未被修改则返回304代码 If-Modified-Since: Sat, 29 Oct 2010 19:43:31 GMT
If-None-Match 如果内容未改变返回304代码,参数为服务器先前发送的Etag,与服务器回应的Etag比较判断是否改变 If-None-Match: “737060cd8c284d8af7ad3082f209582d”
If-Range 如果实体未改变,服务器发送客户端丢失的部分,否则发送整个实体。参数也为Etag If-Range: “737060cd8c284d8af7ad3082f209582d”
If-Unmodified-Since 只在实体在指定时间之后未被修改才请求成功 If-Unmodified-Since: Sat, 29 Oct 2010 19:43:31 GMT
Max-Forwards 限制信息通过代理和网关传送的时间 Max-Forwards: 10
Pragma 用来包含实现特定的指令 Pragma: no-cache
Proxy-Authorization 连接到代理的授权证书 Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Range 只请求实体的一部分,指定范围 Range: bytes=500-999
Referer 先前网页的地址,当前请求网页紧随其后,即来路 Referer: http://www.zcmhi.com/archives/71.html
TE 客户端愿意接受的传输编码,并通知服务器接受接受尾加头信息 TE: trailers,deflate;q=0.5
Upgrade 向服务器指定某种传输协议以便服务器进行转换(如果支持) Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11
User-Agent User-Agent的内容包含发出请求的用户信息 User-Agent: Mozilla/5.0 (Linux; X11)
Via 通知中间网关或代理服务器地址,通信协议 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 关于消息实体的警告信息 Warn: 199 Miscellaneous warning

Responses 部分

Header解释示例
Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
Content-Encoding web服务器支持的返回内容压缩编码类型。 Content-Encoding: gzip
Content-Language 响应体的语言 Content-Language: en,zh
Content-Length 响应体的长度 Content-Length: 348
Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.htm
Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
ETag 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2010 16:00:00 GMT
Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location: http://www.zcmhi.com/archives/94.html
Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic
refresh 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持) Refresh: 5; url=http://www.zcmhi.com/archives/94.html
Retry-After 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 Retry-After: 120
Server web服务器软件名称 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
Set-Cookie 设置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
Trailer 指出头域在分块传输编码的尾部存在 Trailer: Max-Forwards
Transfer-Encoding 文件传输编码 Transfer-Encoding:chunked
Vary 告诉下游代理是使用缓存响应还是从原始服务器请求 Vary: *
Via 告知代理客户端响应是通过哪里发送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
Warning 警告实体可能存在的问题 Warning: 199 Miscellaneous warning
WWW-Authenticate 表明客户端请求实体应该使用的授权方案 WWW-Authenticate: Basic

更多参见 w3c官网 Header Field Definitions

Sep 3, 2014

RTMP(Real Time Messaging Protocol)

  • 流媒体
  • RTMP

RTMP(Real Time Messaging Protocol)实时消息传送协议是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输 开发的开放协议。

RTMP协议是被Flash用于对象,视频,音频的传输.这个协议建立在TCP协议或者轮询HTTP协议之上. 就像一个用来装数据包的容器,这些数据既可以是AMF格式的数据,也可以是FLV中的视/音频数据. 一个单一的连接可以通过不同的通道传输多路网络流.这些通道中的包都是按照固定大小的包传输的.

RTMP有三种变种:

  1. 工作在TCP之上的明文协议,使用端口1935;
  2. RTMPT封装在HTTP请求之中,可穿越防火墙;
  3. RTMPS类似RTMPT,但使用的是HTTPS连接

RTMP被Adobe开发出来,就是用于在其Flash平台的流媒体系统之间传递数据,最简单的Flash流媒体系统由两部分组成:

客户端:采用Flash Player播放
服务器端:
  1. Flash Media Server(FMS):Adobe官方的流媒体服务器。
  2. Red5:开源流媒体服务器,基于Java的。