浏览模式: 标准 | 列表

以前发布的 PHPRPC 3.0 的 JavaScript 客户端 是通过 script 标签来支持跨域调用的,因此限制了参数的长度不可能太长,并且如果页面不是 UTF-8 编码时,也不能跟服务器进行交互,原因是 script 没办法指定单独的 HTTP 头。前些日子发布的 ActionScript 3.0 版本的 PHPRPC 3.0 客户端是 通过 POST 来提交数据的,Flash 的跨域调用机制跟浏览器中的 XMLHTTPRequest 对象的跨域机制不同,Flash 的跨域调用限制可以通过在服务器端部署一个 crossdomain.xml 文件来进行限制。因此 ActionScript 3.0 版本的 PHPRPC 3.0 客户端是可以跨域的,而且服务器端还可以限制跨域的条件。前几天有位朋友建议我 给 JavaScript 跨域调用增加无参数长度限制的能力,他给出的方案是对 GET 请求分包传送,不过因为这种方法需要修改 PHPRPC 协议,目前的客户端和服务器端实现也都要作出修改才可以支持,而且就算实现了效率方面也不会很高,因此我突发奇想,如果在 JavaScript 中调用 Flash 的 ActionScript 3.0 的 PHPRPC 3.0 客户端不就既可以支持跨域,又没有参数长度限制了吗?而且因为 ActionScript 3.0 的执行效率比 JavaScript 高,所以,加密传输也会更快!ActionScript 3.0 里面跟服务器端交互是单独指定的 HTTP 头,因此也不会有页面非 UTF-8 编码时不能跟服务器交互数据的问题了。

于是,花了 2 天时间终于搞了一个跟原来 JavaScript PHPRPC 3.0 客户端使用方法相同的通过 ActionScript 3.0 跟 JavaScript 交互来实现的支持跨域无参数长度限制的 JavaScript PHPRPC 3.0 客户端。实现中当然遇到了一些问题,不过我单独写了一篇关于这些问题和解决办法帖子,这里就不罗嗦了。下面说一下这个 JavaScript PHPRPC 3.0 客户端跟原来的那个有什么不同之处:

1、新的这个 JavaScript 客户端需要在 HTML 的 body 插入 phprpc_flash.js 脚本(通过 script 标签来引入该文件),这段脚本不能放在 head 中,也不能放在 form 中。另外,要保证 phprpc_flash.js 中引用的 phprpc_client.swf 文件的路径是正确的。

2、都支持目前常见的浏览器,如:IE, Mozilla/Firefox,Opera,Safari 等。但是在非跨域的情况下,原来的 JavaScript 客户端对手持设备(例如 Pocket PC,SmartPhone,iphone 等)支持的更好,而新的这个 JavaScript 客户端因为需要 Flash9 的支持,在目前的手持设备上都不支持。

3、新的这个 JavaScript 客户端不支持 abort、setTimeout 和 getTimeout 这三个方法。因为在 ActionScript 3.0 版本的 PHPRPC 客户端里面也没有提供这三个方法。不过还好,这三个方法都是不常用。

4、在 JavaScript 中定义的对象,通过这个客户端传给服务器时,可能会变成 Hash 表(比如 PHP 中的 Array,Java 中的 HashMap,.NET 中的 HashTable),因为 JavaScript 跟 ActionScript 3.0 交互时,会在内部进行一次序列化和反序列化(Flash 本身处理的,而不是 PHPRPC 的序列化和反序列化)。

5、JavaScript 中的递归定义的对象,无法通过该客户端跟服务器通信,原因同第 4 条。因为 Flash 内部的这种 JavaScript 跟 ActionScript 3.0 之间的序列化和反序列化不支持递归对象。

今天把整个代码重写了一下,这次只使用 AS3 中的 URLLoader 来实现 POST 数据,而不再直接使用 AS3 版本的 PHPRPC 客户端,并且在非跨域情况下,仍然使用 XMLHttpRequest 来提交数据,因此,原来列举的上面那些不同的问题,除了第一条之外,2、3、4、5 都已经解决,跟原来的纯 JavaScript 版本完全一致了。

下载地址请访问 PHPRPC 官方网站:http://www.phprpc.org

» 阅读全文

这两天做基于 Flash9(ActionScript 3.0)的 JavaScript PHPRPC 3.0 客户端时遇到了一些 JavaScript 与 ActionScript 3.0 交互的一些问题,这些问题在网上基本上都没有找到答案,最后通过不断的尝试才得以解决,因此在这里总结出来,希望能给遇到同样问题的同志们一些帮助。

JavaScript 跟 ActionScript 3.0 交互也是通过 flash.external.ExternalInterface 这个类,不过与跟 Flash 8 中跟 ActionScript 2.0 交互所使用的 flash.external.ExternalInterface 还是有所不同的。最大的不同就是 ExternalInterface.addCallback 方法在 ActionScript 3.0 中只有 2 个参数了,而不再有 instance 这个参数。下面要讨论的这些问题都是关于 Flash 9 中 ActionScript 3.0 的。

先来说最常遇到的问题,就是在 JavaScript 调用 Flash 中的 ActionScript 方法时报告该方法不存在。这个问题是跟 Flash 中执行 ExternalInterface.addCallback 的时间有关的,ExternalInterface.addCallback 必须要在 HTML 的完全载入之后也就是 window.onload 事件执行后才可以执行,否则,它所发布的方法都无法在 JavaScript 中调用。

解决这个问题的方法在 Flash 9 的 ActionScript 3.0 帮助中有个例子,里面包含了这个解决方法,就是首先在 js 中设置两个标志,例如 jsReady 和 swfReady 这两个变量作为标志,开始都设置为 false,当 window.onload 时,设置 jsReady 为 true,在 Flash 中一开始检查 JavaScript 中的这个 jsReady 标志是否是 true(通过 ExternalInterface.call 方法调用 JavaScript 中的返回这个标志的一个函数),如果不为 true,就设置一个定时器,经过一段时间后(例如 50 或 100 毫秒)重复这个检查这个标志,一旦为 true,则执行 ExternalInterface.addCallback 来发布 ActionScript 要提供给 JavaScript 调用的函数或方法,执行完所有的 ExternalInterface.addCallback 后,通过 ExternalInterface.call 方法调用 JavaScript 中的设置 swfReady 标志的函数设置 swfReady 为 true。之后,当 JavaScript 检测到 swfReady 为 true 后,再调用 ActionScript 中的方法就不会遇到上的说的这个问题了。

如果简单一点的调用这样还可以,如果是有好多这样的调用就比较麻烦了。我是通过建立两个执行队列:jsTaskQueue 和 swfTaskQueue,当在 jsReady 为 true 之前,如果有要调用 ActionScript 的操作,就把这个操作放到 jsTaskQueue 中,当 js 在 window.onload 中执行设置 jsReady 时,把这个队列中的任务取出来执行,当 jsReady 为 true 后 swfReady 为 true 之前,如果有要调用 ActionScript 的操作,就把这个操作放到 swfTaskQueue 中,当 ActionScript 通过 ExternalInterface.call 方法调用 JavaScript 中的设置 swfReady 标志的函数设置 swfReady 为 true 时,把这个队列中的任务取出来执行。当 jsReady 和 swfReady 都为 true 时,那么如果有要调用 ActionScript 的操作,直接运行就可以了。通过这种方法把这些任务封装后,使用这些封装之后的操作,在编写代码就可以按照顺序(而不是异步)来写了,执行时也是顺序执行啦。

除了这个最常遇到的问题之外,还有两个关于 IE 上的问题。

如果你是通过 JavaScript 动态创建的 Flash 标签然后插入到 html 中的话(例如通过 innerHTML 赋值的方法或者 appendChild 的方法),很可能你这个操作是在 window.onload 之后才进行,在这种情况下,其它浏览器可以正常进行 JavaScript 和 ActionScript 3.0 的交互,IE 就不行。所以,为了保险,最好的方法就是直接把 flash 标签的 html 写在 html 的 body 中,或者用 JavaScript 的 document.write 来写入 html 的 body 中,后面这种方法对于 IE 来说更合适一些,因为这样的话,可以不需要点击激活 Flash。

另一个问题是,不要在 ActionScript 中发布名字为 invoke 的方法,否则在 IE 中,JavaScript 调用该方法时会出错。

最后一个问题,网上可以查到的比较多了,就是不要把 flash 放到 form 中,否则在 IE 中,JavaScript 调用 ActionScript 时会出错。当然,网上也给出了一个解决这个问题的脚本,不过那个貌似是针对 Flash 8 的 ActionScript 2.0 的,我没有试过,不知道对 ActionScript 3.0 是否同样有效。


11 月 23 日补充:

今天又发现一个问题,如果在 ActionScript 中通过 ExternalInterface.call 调用 JavaScript 时,如果传递的参数有字符串,那么字符串中如果包含 \ 符号的话,那么将会调用失败。这个也是 ActionScript 和 JavaScript 交互的一个 bug,解决办法是,对传递的字符串先进行一下处理在传递,处理方法很简单,比如要传递的数据是 data,将它进行一次 data.replace(/\\/, “\\\\”) 替换之后,在传递给 JavaScript 就可以了。

» 阅读全文

11月
12

PHPRPC Client 3.0 for Perl

这个 PHPRPC 客户端程序支持加密传输,引用参数传递等诸多特征,跟 PHP 版本的客户端的使用方法基本相同。不过因为 PHP 序列化反序列化的包用的是 CPAN 的 PHP::Serialization 这个包,这个包的实现本身有一些问题,比如对负数的反序列化错误,不支持递归引用的序列化和反序列化等,因此,对于某些调用可能会失败,等以后把 PHP::Serialization 完善一下就可以解决了。

PHPRPC Client 3.0 for Perl

不过暂时不再搞 Perl 版本了,接下来改继续做 PHPRPC 3.0 for .NET 啦,好多人都在等待,我都有点不好意思说了。

» 阅读全文

11月
08

XXTEA for Perl

今天开始写 PHPRPC for Perl 了,PHP 序列化反序列化(虽然不算完美,不过可以先凑合用),大数运算,Base64 编码,HTTP 通讯管理的 Perl 包都有现成的,就差一个 XXTEA 算法没有,今天就写了一个,跟本站其它语言(如 PHP、JavaScript、C#、Java、ActionScript 等)实现的 XXTEA 算法兼容,用法也很简单,下面是它的代码,等 PAUSE 的帐号申请下来,就提交到 CPAN 上去,PAUSE 审核一个帐号竟然需要 3 个星期,办事效率快赶上我们的公务员了,呵呵。

感谢小西同学帮我校对注释!

» 阅读全文