|
Javascript中實(shí)現(xiàn)這個(gè)功能的是來(lái)自BOM的一個(gè)函數(shù)setTimeout,但相關(guān)的DOM操作也提供了一系列實(shí)現(xiàn)。如XMLHttpRequest對(duì)象與script標(biāo)簽的onreadystatechange回調(diào),image的onload與onerror回調(diào),iframe的onload,DOM元素的事件回調(diào),HTML5的跨域消息傳送postMessage,QuickTime與flash對(duì)象的加載……
setTimeout的零秒延遲在前些年時(shí)間被國(guó)內(nèi)宣揚(yáng)得特別厲害,但setTimeout是所有延遲中最慢的,最少要花上10多毫秒,如果用setTimeout來(lái)開(kāi)發(fā)特效,這特效會(huì)運(yùn)行得比較慢。下面是一個(gè)性能測(cè)試:
[Ctrl+A 全選 注:如需引入外部Js需刷新才能執(zhí)行]
Chromium | Safari | Firefox | Opera 10.10 | Opera 10.50 | |
---|---|---|---|---|---|
setTimeout | 4.32ms | 10.201ms | 10.302ms | 10.38ms | 9.876ms |
img.onerror | 0.199ms | 0.678ms | 0.201ms | 0.058ms | 0.575ms |
script.onreadystatechange | fail | fail | fail | fail | fail |
script.onload | 0.414ms | 0.138ms | 0.414ms | fail | fail |
xhr.onreadystatechange | fail | 0.622ms | fail | 0.078ms | 0.079ms |
self.postMessage | 0.096ms | 0.123ms | 0.112ms | 0.049ms | 0.094ms |
為了處理這種異步調(diào)用,Mochikit從Python的Twisted框架借來(lái)了Deferred這個(gè)類,并用它來(lái)處理AJAX的回調(diào)。AJAX的回調(diào)通常有兩種,成功加載時(shí)的回調(diào)與請(qǐng)求失敗的回調(diào),IE8的XDomainRequest就有這兩種回調(diào)了,標(biāo)準(zhǔn)瀏覽器的script與image也有這兩種回調(diào),分別稱之為onload與onerror。Mochikit的Deferred實(shí)例就內(nèi)置一個(gè)數(shù)組,每次包含這兩種回調(diào),依次執(zhí)行。Mochikit這偉大的遺產(chǎn)后來(lái)由dojo發(fā)揚(yáng)光大了,至于怎么用,自己google吧。
下面是我的框架對(duì)它的應(yīng)用,我已把它整合到我的框架中:
復(fù)制代碼 代碼如下:
<!doctype html>
<html>
<head>
<title>異步操作例子 by 司徒正美</title>
<meta charset="utf-8"/>
<meta content="IE=8" http-equiv="X-UA-Compatible"/>
<meta name="keywords" content="異步操作例子 by 司徒正美" />
<meta name="description" content="異步操作例子 by 司徒正美" />
<%= Javascript_include_tag "dom.js" %>
<%= Javascript_tag "window._token = '#{form_authenticity_token}'" if ActionController::Base.allow_forgery_protection %>
<script type="text/Javascript" charset="utf-8">
dom.ready(function(){
dom.require("ajax");
dom.ajax({method:"post",
async:true,
dataType:"text",
data:{authenticity_token:window._token}
}).next(function(a){
alert(a)
});
dom.jsonp({url:"http://del.icio.us/feeds/json/fans/stomita"}).next(function(json){
alert(json)
}).error(function(e){
alert(e)
});
});
</script>
</head>
<body>
</body>
</html>
后臺(tái):
復(fù)制代碼 代碼如下:
class HomeController < ApplicationController
def index
if request.xhr?
name = params[:name]
puts "-------------"
render :text => "<p>The time is <b>" + DateTime.now.to_s + "</b></p>"
end
end
end
在日本一博客提到這樣一個(gè)捕捉異步錯(cuò)誤的例子:
復(fù)制代碼 代碼如下:
function throwError(){
throw new Error('ERROR');
}
try{
setTimeout(throwError, 3000);
} catch(e){
alert(e);
}
看來(lái)try...catch是無(wú)法捕捉這種形式的錯(cuò)誤,window.onerror可以,但好像只有IE與FF支持。如果用Deferred來(lái)處理,就簡(jiǎn)單了!
復(fù)制代碼 代碼如下:
dom.Deferred.next(function () {
throw new Error("錯(cuò)誤")
}).wait(1).error(function(e){
alert(e instanceof Error)
});
列隊(duì)處理。由于是使用了異步,因此不會(huì)阻塞頁(yè)面的演染。
復(fù)制代碼 代碼如下:
<!doctype html>
<html>
<head>
<title>異步操作例子 by 司徒正美</title>
<meta charset="utf-8"/>
<meta content="IE=8" http-equiv="X-UA-Compatible"/>
<meta name="keywords" content="異步操作例子 by 司徒正美" />
<meta name="description" content="異步操作例子 by 司徒正美" />
<%= Javascript_include_tag "dom.js" %>
<script type="text/Javascript" charset="utf-8">
dom.require("deferred");
dom.require("query");
dom.ready(function(){
var a = dom("#aaa")[0];
dom.Deferred.loop(10,function(i){
a.innerHTML += i+"<br/>"
});
dom.Deferred.loop(10,function(i){
a.innerHTML += String.fromCharCode(i+97)+"<br/>"
});
dom.Deferred.loop(10,function(i){
a.innerHTML += "司徒正美"+i+"<br/>"
});
});
/*結(jié)果
0
a
司徒正美0
1
司徒正美1
2
c
司徒正美2
3
d
司徒正美3
4
e
司徒正美4
5
f
司徒正美5
6
g
司徒正美6
7
h
司徒正美7
8
i
司徒正美8
9
j
司徒正美9
*/
</script>
</head>
<body>
<div id="aaa"></div>
</body>
</html>
JavaScript技術(shù):javascript異步編程,轉(zhuǎn)載需保留來(lái)源!
鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標(biāo)記有誤,請(qǐng)第一時(shí)間聯(lián)系我們修改或刪除,多謝。