ngx_http_fastcgi_module的那些事

是什么?

顾名思义,是Nginx用来处理FastCGI的模块。FastCGI是什么?这个以后再讲,可以说的是现在LNMP架构里面,PHP一般是以PHP-CGI的形式在运行,它就是一种FastCGI,我们在进程中看到的PHP-FPM是PHP-CGI的管理调度器。

为什么要详解一下?

因为LNMP不像LAMP,且早期Nginx不支持path_info,导致网上有大量旧版本的Nginx教程干扰视线。

为了更加清晰准确使用LNMP,估需要深入了解一下整个ngx_http_fastcgi_module。 继续阅读“ngx_http_fastcgi_module的那些事”

jQuery进阶,$.Deferred() 延迟对象

JS里面有大量的异步方法,写着写着,代码就会变得>>。多层嵌套的回调,很影响后续代码的维护,也许今天你还记得这块回调逻辑,明天你就很有可能被这回调姿势给坑了。

那么,今天就介绍一种抹平回调的方法,jQuery.Deferred。

$.Deferred() 是什么?

$.Deferred() 从字面上理解,就是一个延迟对象。它是jQuery出的,为了解决回调嵌套,方便开发者的一种函数。

好像好高深,其实我们很早就有接触,并经常在用到。

jQuery的$.ajax()本身就支持Deferred,它可以链式补上 .done()  .fail() 等方法来处理不同状态的结果。

$.Deferred()有什么用?

例如动态获取一张图片的宽度

当调用 getImgWidth() 的时候,其返回值没法获取到正确的宽度,而随后当图片加载完成触发load事件后,alert出来的宽度才是正常的。

那么,我们改怎么修改这个方法呢?

这段升级后的函数,再获取的宽度的时候,就可以使用如下方法轻松获得

看完这段改造后的代码,也许有人会说,这个作用不大呀,和直接给 getImgWidth(callback) 加多一个回调函数没什么区别。

嗯,从这里来看,貌似是这样,但是,当我们要同时处理多个异步的时候,$.Deffered()的威力就体现出来了。

比如,需求是同时加载完两张图片,得到两个宽度之后,才开始执行后续逻辑。

传统的回调要怎么写?反正我是晕了。

用$.Deferred()就很简单,getImgWidth()的定义不变,使用$.when()方法来处理同时完成的事件。

怎样,有没发现突然晴空万里,以前的业务逻辑里面各种为了解决多个异步条件的setTimeout()是不是瞬间变得很没用。

$.Deferred() 小结

拥抱Deferred,抛弃那些不可控的setTimeout()吧。

最后引用阮一峰的《jQuery的deferred对象详解》里面的小结吧:

  • $.Deferred() 生成一个deferred对象。
  • deferred.done() 指定操作成功时的回调函数
  • deferred.fail() 指定操作失败时的回调函数
  • deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法被改变;接受参数时,作用为在参数对象上部署deferred接口。
  • deferred.resolve() 手动改变deferred对象的运行状态为”已完成”,从而立即触发done()方法。
  • deferred.reject() 这个方法与deferred.resolve()正好相反,调用后将deferred对象的运行状态变为”已失败”,从而立即触发fail()方法。
  • $.when() 为多个操作指定回调函数。
  • deferred.then() 有时为了省事,可以把done()和fail()合在一起写,这就是then()方法。

PushPlugin-为iOS的Hybird App提供APNS服务

APNS是什么?

APNS是iOS生态下面的推送机制。其原理是APP启动的时候,向苹果注册,并获得一个唯一token,然后不论app是否继续在运行,都可以通过调用苹果的APNS服务,来向持有token的设备推送消息,例如顶部的通知。

之前有SSE了,为什么还要APNS?

一开始我也分不清,后来发现,APNS可以在应用关闭的时候,通过iOS系统的通知栏,推送消息给用户,让用户重新进入app中执行某些事情。而这些,是SSE做不到的,SSE仅仅是一套消息机制,必须有app运行的时候才有效。

说了这么久,怎么用?

参考这篇文章:https://github.com/phonegap-build/PushPlugin#automatic_installation

使用方法:

1、安装PushPlugin插件

cordova plugin add https://github.com/phonegap-build/PushPlugin.git

2、配置插件

这个是我把官方的例子,做了一下AMD的封装,使用的方法如下。

然后,就没有然后了。留意tokenHandler里面的结果,收集下来,然后就可以给服务端。app启动后,就可以随时接收服务端的信息了。

看上去很简单,为什么用了这么多时间?

嗯,APP端很简单,但是服务端涉及到各种证书,有点弄不清,然后官方的文档又都是全英,半桶水英语看得够呛。

PushPlugin为我们准备了Example目录,里面的server端有ruby的脚本供我们测试。

测试前的准备:

  1. Ruby的环境
  2. 上面已经装好PushPlugin的APP
  3. 安装pushmeup  sudo gem install pushmeup

接下来就是看得我头晕的生成pem的过程。

  1. 我也懒得翻译了,直接参考这篇文章,获得ck.pem文件。
  2. 编辑Example/server/pushAPNS.rb,配置里面的pem、pem密码和接收消息设备的token。
  3. 执行脚本,向设备推送消息。 ruby pushAPNS.rb

PushPlugin使用小结

客户端安装PushPlugin,并配置好register的时机,同时,在获取到token之后,将token上报给服务端。

服务端按照苹果的要求,配置好各种证书后,向持有token的设备下达消息。

不论app是否仍在运行,设备都将会受到这条消息。

iOS开发者证书-2015年中文版

我们都知道,制作一款iOS的App需要iOS的开发者证书。在Apple的开发者网站上面,有一个栏目是‘Certificates, Identifiers & Profiles’。这三个东西,对于一开始接触的人,实在是一头雾水。

Certificates 证书,如开发者证书

  • Development
    • iOS App Development 开发者证书
    • Apple Push Notification Service SSL(Sandbox)
  • Production
    • App Store and AD Hoc 发布证书
    • Apple Push Notification service SSL (Production)
    • Pass Type ID Certificate
    • Website Push ID Certificate
    • VoIP Services Certificate
    • Apple Pay Certificate

在证书这栏,我们主要关注开发者证书和发布证书这两个。

开发者证书是和Mac相关联的,由Mac上面的‘证书管理’请求证书,生成一个*.certSigningRequrest的文件。将该文件提交到开发者网站上面,即可生成对应的开发者账号证书。

发布证书则是发布应用的时候才需要的。

Identifiers 唯一识别码

  • App IDs App的唯一ID,也就是Xcode里面的Bundle-id
  • Pass Type IDs
  • Website Push IDs
  • iCloud Containers
  • App Groups
  • Merchant IDs

这里,我们暂时只需要关注App IDs,为我们的应用创建一个Bundle-id,并且配置对应的一些功能(部分功能需要再申请对应的证书文件)。

Devices 设备

  • All 全部

硬件这栏没有二级菜单,里面显示的全部测试设备的UDID,一个开发者账号可以有100个UDID。

通过Ad-hoc方式进行测试分发,需要收集测试设备的UDID,测试设备才能安装上。

之前pgyer.com提供她们的企业证书,供第三方来二次打包,并以企业分发的形式进行供外部用户进行测试。但在Apple收购了TestFlight之后,这部分策略被收紧了。

现在进行分发测试,要么自己买企业证书,要么自己收集UDID,要么走苹果的TestFlight外部测试的流程(这个测试发布,也是要经过苹果审核的)。

Provisioning Profiles 描述文件

  • All
  • Development 开发描述文件
    • iOS App Development 开发者证书描述文件,用来关联App ID、开发者证书、测试硬件之间的关系
  • Distribution 分发描述文件
    • App Store 应用市场的描述文件, 用来关联App ID、发布证书之间的关系
    • Ad Hoc 测试分发的描述文件,用来关联App ID、发布证书、测试硬件之间的关系

晕了没?反正我是晕了。总结以下就是:

  • 需要一个开发证书,这个证书是和Mac\Xcode有关系的。
  • 需要一个App ID,来作为你的软件的唯一标示。
  • 需要一个描述文件,这个文件是用来绑定你的证书和App ID的。

还有

刚才上面的这些东西,都是在开发者网站上面进行配置的,然后每次变更,最后Xcode都要关掉重启,以便能正确加载最新的关系。

然后,Xcode自己也会生成、维护一套证书关系,所以,一个不小心,你在Apple开发者网站上面的各种证书描述文件会满天飞。

再然后,上面提到的是单个开发者的,如果是多个开发者,同时使用一个开发者账号,那又会出现各种诡异的证书描述文件错误问题。

利用H5的EventSource,小试服务器推送(SSE)

H5在最后定稿的时候,出现了一个新的JS API:EventSource(也许是我之前一直没关注吧)。

EventSource有什么用呢?简单来说,就是实现Web端的服务器主动推送功能(SSE,Server-Sent-Events)。

废话少说,先上一段代码:

这段代码运行后,会开始监听服务器推送的事件,例如任意时刻,sse.php输出一句hello world,客户端的console就会立马有输出。

我们来深入了解一下。

窥探EventSource细节:

首先, new EventSource(url) ,客户端会立马向该url发出一个HTTP请求(没错,的确是HTTP请求,整个SSE都是建立在HTTP协议上面的,这是于WebSocket的本质区别),然后观察这个HTTP的Header,它的MIME类型是text/event-stream。

text/event-stream是专门为SSE设计的MIME类型,这个是构造SSE请求的关键。

当服务端收到接到请求后,会hold住这个请求,当需要服务端推送数据的时候,才往这个请求中返回所需要的信息,以 data:'这个是返回的消息内容' 格式的写入,并利用HTTP/1.1中的分块传输的机制,立马刷新缓存中,输出内容并不释放连接,当有下一个内容需要推送的时候,又立马扔到HTTP的返回中。

上面的流程是不是很熟息?和以前的长连接的玩法很像?SSE就是把原来的HTTP长连接的玩法给标准化了。

继续阅读“利用H5的EventSource,小试服务器推送(SSE)”

使用jQuery.data()查看元素上绑定的事件

最近遇到一个诡异的问题,发现我添加在一个HTMLElement片段上面的事件绑定,会在后续的流程中,无故丢失了。但是,我不知道它是什么时候丢失的。

所以我需要要一步步逼近定位到问题。

最先想到的是浏览器面板上面的,可以选中元素,看元素上面的事件绑定。

但浏览器上面看到的是结果量,也就是看到的是已经丢失了事件的元素,但我还是不知道什么时候丢失的。

估一路断点,观察、回溯调用栈(Sources面板右侧的Call Stack)。

然后问题来了。

我可以断点取到每个阶段的HTMLElement元素的状态,但是,这个时候,我却找不到观察其事件绑定情况的方法。

谷歌好久,发现JS原生是没法查看事件绑定情况的。

还好,我们都是用的jQuery,用的$.on()。

而jQuery自身事件绑定,额外添加了一层事件数组。(也是这个原因,$.on()可以重复给一个元素的同一个事件绑定多个handler,而直接addEventListener则只能绑定一个,后面的会覆盖掉前面的)

扯了这么多,show me the code:

然后,就会返回这个元素上面绑定的所有事件。如下图

jQuery.data(‘events’)

套壳

phonegap已经不再是phonegap,而是phonegap build,用来打包的。

以前phonegap中,用来JS与native通信的模块,现在叫做cordova,也就是现在要套壳的话,是套cordova。

安装

坑一:公司内网,公司内网npm镜像会遇到部位外链依赖下载不了。

坑二:部分npm包在安装的时候需要编译,Mac默认没有安装编译器(如Linux的GCC),需要手动安装Xcode Command Line Tools。

坑三:用外网吧,内网无形中增加各种bug。

初始化项目

此时,helloWorld目录下面,会有www目录,将我们的页面放到该目录中,并在页面中引入cordova.js

编译cordova,生成Xcode的项目

两个命令的区别在于:

prepare,在Xcode里面需要再build,才能运行。

build,在Xcode中不需要再build,可直接运行。

此时在helloWorld/platforms/ios里面,就有了我们iOS的项目代码,此时可以直接Xcode打开,并编译运行,有证书的还可以真机运行测试。

调用二维码插件

https://github.com/wildabeast/BarcodeScanner

安装插件的方式,在终端里面,输入

然后重新执行一次cordova的编译

这个时候,在页面中,就可以通过如下方式调用扫描二维码功能了。

使用插件注意事项

1、cordova.js文件必须置于cordova生成的www目录下面。

2、 cordova plugin add 方式安装完插件后,cordova_plugin.js的内容会变成我们插件的相关依赖(例如这里会变成AMD的方式声明依赖barcodeScanner.js文件)。

3、我们不需要在页面写明引入cordova_plugin.js和barcodeScanner.js。只需要再执行 cordova prepare 一次,cordova.js会自动引入cordova_plugin.js到页面中,并将相关插件(barcodeScanner.js)引入到页面中。