google closure 笔记-client-server数据交互,XhrIo,Uri

1,goog.net.XmlHttp

此类的作用是,根据当前的浏览器环境,创建一个正确的XMLHttpRequest/ActiveXObject 对象(这个是原生的对象)。

同时定义了goog.net.XmlHttp.ReadyState ,其中分别定义了readystate 0-4的名字。

此类是一个基础类,作用是为其他类提供一个可以跨浏览器的XHR对象,因此不建议直接使用此类


2,goog.net.XhrIo

一般使用此类来进行ajax通信。

此类继承自EventTarget,其内部使用XmlHttp来实现。基本原理是:创建XmlHttp来实现基本的通信功能,对XmlHttp的不同状态,触发相应的事件goog.net.EventType,并对浏览器的差异进行处理。

此类还提供了一个静态的send方法,因此如果只是很简单的通信,可以直接使用goog.net.XhrIo.send(xxxxx);但是一般通过new good.net.XhrIo 来创建对象,然后用注册监听的方法实现其他功能。

源码解析:

goog.net.XhrIo(opt_xmlhttpFactory):构造方法,可以传入一个工厂函数来产生XHR对象,否则使用默认的工厂函数。

并继承自EventTarget,因此是一个标准的事件源,可以用listen来注册监听。

goog.net.XhrIo.sendInstances_:用静态send方法所产生的对象都存在这里,以方便统一销毁。

goog.net.send():静态方法,其原理是创建一个临时的XhrIo对象来进行通信,然后再销毁这个对象。注意在这里是将回调函数注册到了complete事件上而不是success事件上,所以请求错误也会调用回调函数。

     timeout参数是全局的,而不是这个临时对象专有的。

goog.net.prototype.send():创建一个XHR进行通信,并将注册onreadystatechange = this.onreadystatechange_,

goog.net.prototype.onreadystatechange_():调用了onReadyStateChangeHelper_ 。

goog.net.prototype.onReadyStateChangeHelper_():在此函数中,根据相应的状态,触发了对应的goog.net.EventType事件。

goog.net.prototype.getResponseText():获得返回结果的文本

goog.net.prototype.getResponseJson():调用goog.json.parse来将返回文本解析成json数据并返回。


注意:使用send静态方法时要注意xhr对象的生命周期。

当使用静态send方法时,在回调函数执行完后会销毁xhr实例,所以如下使用是错误的:

goog.net.XhrIo.send('http://www.example.com/testdata.txt', function(e) { 

var xhr = /** @type {goog.net.XhrIo} */ (e.target);

// Instead of doing the alert right away, call it in a timeout. setTimeout(function() { alert(xhr.getResponseText()); }, 1000);

});

因为setTimeout是在新的线程中异步执行的,但是此时xhr对象已经被销毁,所以会导致错误。如下方法才是正确的:

goog.net.XhrIo.send('http://www.example.com/testdata.txt', function(e) { 

var xhr = /** @type {goog.net.XhrIo} */ (e.target);

var responseText = xhr.getResponseText();

setTimeout(function() { alert(responseText); }, 1000);

});

在xhr被销毁之前,把需要用的responseText取出来存在另外一个变量中,就可以避免在异步访问中发生错误。


3,goog.net.EventType

注意两个常用的类型的区别:COMPLETE和SUCCESS

无论是否发送成功,总是会触发COMPLETE事件,包括 由于 超时,服务器端错误,网络故障等造成的错误。

但是SUCCESS只有在请求成功时才会触发,触发顺序如下:

->complete->success/error/abort


4,goog.net.XhrManager

使用prioritypool来管理所有的xhr请求,当xhr资源可用时,会自动挑选最高优先权的xhr来执行。当一个页面需要大量的发送xhr请求时,可以使用xhrmanager来做。

优点:

自动管理优先级

自动管理大量的并发请求

可以自动重发失败的请求


两个重要方法:

goog.net.XhrManager(opt_maxRetries, opt_headers, opt_minCount, opt_maxCount, opt_timeoutInterval):构造函数,maxRetries:请求失败后,最多重发次数。

 headers:指定头部, minCount:pool中最少存在的xhr数量,maxCount:最大数量。timeoutInterval:超时时间。

因为是在xhrmanager的构造函数中传入的参数,所以这些设置是此manager中所有xhr公用的。

goog.net.XhrManager.prototype.send(

     id: 此请求的id,这个id是必须的,之后想操作这个请求,比如:取消它,就需要用到这个id。

     url:请求的url。

     opt_method:回调函数

     opt_content:

     opt_headers:

     opt_priority:

     opt_callback:

     opt_maxRetries:

}

创建XhrManager对象之后可以直接使用此方法来发送请求。


5,goog.Uri

封装了对uri的常用操作,类似于location对象中的方法,但是比它强大。用法如下

var googUri = new goog.Uri(uri);

googUri.getScheme(); googUri.getUserInfo(); googUri.getDomain(); googUri.getPort(); googUri.getPath(); googUri.getQuery(); googUri.getFragment();

同get方法还有对应的set方法。

如果不想new一个对象,可以使用对应的goog.uri.utils.xxx静态方法,可以直接对uri字符串进行操作

goog.uri.util.getScheme("http://www.baidu.com") == (new goog.Uri("http://www.baidu.com")).getScheme();


getQuery(在utils中是getQueryData)方法:会返回一个QueryData对象。类似于一个map,不过不同的是这个map是一对一或者一对多的关系。

因为同一个参数可能被多次赋值,这是允许的。比如:?a=1&a=2&a=3


6,goog.net.BulkLoader

假设想从多个url请求数据,并处理这些数据的集合,则可以使用BulkLoader。

bulkloader可以从一个urls数组获取数据,并把结果按照url的顺序存在一个数组并返回。

它的好处是 可以保证返回结果的顺序和请求地址中的顺序对应,并封装了对错误的处理。

var bulkLoader = new goog.net.BulkLoader(urls); goog.events.listen(bulkLoader,

[goog.net.EventType.SUCCESS, goog.net.EventType.ERROR], function(e) {

if (e.type == goog.net.EventType.SUCCESS) {
// We use unsafeParse here because we trust the source of the data. var loader = /** @type {goog.net.BulkLoader} */ (e.target);
var json = goog.array.map(loader.getResponseTexts(),

goog.json.unsafeParse), showEventsOnCalendar(json);

} else {
// Here, e.type is goog.net.EventType.ERROR

alert('Oh no - I should add some error handling here!'); }

bulkLoader.dispose(); });

bulkLoader.load();

源码解析:

goog.net.BulkLoader(urls):构造函数,传入一个参数是url的数组。此类是EventTarget的子类。内部保存了一个BulkLoaderHelper的实例helper_。

bulkload主要做的是:新建一个BulkLoaderHelper实例,将urls传给他。然后从urls中诸葛取出url,创建xhr,把返回结果和序号交给bulkloaderhelper保存。

load():取得数据。遍历urls数组,对每一个url,新建一个xhr链接取数据,回调函数handleEvent_,注意这里将对应的index传给了handleEvent_。

handleEvent_(id,e):如果成功,则handleSuccess_(id, xhrIo);失败则handleError_(id, xhrIo);

handleSuccess_(id, xhrIo):调用helper_.setResponseText(id, xhrIo.getResponseText),传入的是当前url的index和返回结果。然后调用helper_.isLoadComplete()来判断是否加载完毕,如果是,则调用finishLoad_()来触发SUCCESS事件。

handleError_(id, xhrIo):触发ERROR事件。handleSuccess_和handleError_最后都会调用xhrIo.dispose()来销毁对象。


goog.net.BulkLoaderHelper(uris):保存uris_,建立一个responseTexts_空数组用来存储返回结果。其作用就是管理uris和responseText_两个数组。

getUri(id):return this.uris_[id]; 

getUris():return this.uris;

setResponseText(id, responseText):把responseText存在this.responseTexts[id]中。

getResponseTexts():return this.responseTexts_;

isLoadComplete():遍历this.responseTexts_数组,如果其length和uris.length一样,并且其中每一项都已经被赋值,则返回true,否则返回false。


7,goog.net.ImageLoader:

可以并行地加载多个图片资源。比如程序需要加载多张图片之后执行某些操作,或者想在加载网页其他部分的时候预加载图片,可以使用此类来实现。

原理:创建Image实例(new Image();或者 createElement("img"),其实就是一个DOM元素<img>),然后赋值img.src="xxx",此时浏览器会自动发送请求加载图片。加载完成后,可以读取图片的信息(比如img.width),如果传入的构造参数是一个img元素,则此图片会直接显示。


var loader = new good.net.ImageLoader();

loader.addImage("img-1","http://www.baidu.com/img/baidu_sylogo1.gif");//添加一个img。

loader.start();//开始加载所有图片。


8,goog.net.IframeLoadMonitor

当iframe加载完成后触发一个事件(无论是加载成功还是失败)。


9 跨域通信

http://example.com/mypage.html为例,以下情况都算作跨域通信:

URL                                                  Why access is denied

http://google.com/                                Different domain

https://example.com/mypage.html   Different protocol

http://example.com:8080/index.jsp  Different port 

http://www.example.com/mypage.htmlDifferent subdomain


ajax是不能进行跨域通信的,closure提供了两个跨域通信的工具:goog.net.Jsonp 和 goog.net.xpc


9.1 goog.net.Jsonp

jsonp用来进行跨域通信。其原理是:创建一个script标签,指定src属性值,此时浏览器会自动发送请求获取内容并执行其中的js代码。

示例:

var jsonp = new goog.net.Jsonp('http://example.com/birthdays', 'callback');
// By default, the JSONP request is cancelled if it does not return within // 5 seconds, so this increases the timeout to 10 seconds. jsonp.setRequestTimeout(10 * 1000);
var errorCallback = function() {
alert('The request failed to return within 10 seconds'); };
// The send() method is responsible for creating and destroying the <script> // tag that points to example.com.
jsonp.send(null /* payload */, showBirthdays, errorCallback);


源码解析:

goog.net.Jsonp(uri, opt_callbackParamName):构造函数,第一个参数是uri,第二个参数是uri后面的callback参数名(注意,不是请求成功后的回调函数,也不是callback参数值,而是 www.xx.com?callback=abc中的callback名),如果不设定,则默认是callback。

goog.net.Jsonp.send(

opt_payload,  以get方式添加的参数,name-value类型的

opt_replyCallback, 请求成功后的回调函数,会传一个参数就是请求的返回结果

opt_errorCallback,  请求失败后的回调函数,会把opt_payload当参数穿进去

opt_callbackParamValue  opt)  callbackParamName参数的值

);

发送请求。

创建一个script标签。然后设置timeout以在超时后调用error函数执行超时操作。创建一个uri,并追加相应的参数(payload等)。

把对应的callback存储在goog.global[goog.net.Jsonp.CALLBACKS][id]中,这个id是自动生成的唯一标示。 

将script标签赋值src,并append到head中(此时浏览器会自动发请求加载内容,并执行其中的js代码)

9.2 goog.net.xpc

另一个跨域通信的类,主要用来在不同域的iframe之间进行通信。

先有必要了解下window.postMessage:

新特性,可以用来在不同域的iframe之间进行通信。

例如:在iframe0中:

frame = window.iframe[1]; frame.postMessage(xxx);     //获取一个iframe1引用,并用它来发送一个信息。

在iframe1中:

window.addEventListener("message", callback);     //iframe中可以捕获上面发送的那个消息。

你可能感兴趣的:(浏览器,iframe,function,url,callback)