<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    【永恒的瞬間】
    ?Give me hapy ?

    翻譯了一篇kuwamoto以前的一篇關于如何處理異步事件的日志。這一系列共有三部分,我會陸續(xù)把他們都翻譯出來,今天先貼出來第一部分。

    原文地址:http://kuwamoto.org/2006/05/16/dealing-with-asynchronous-events-part-1/

    原文作者: Sho Kuwamoto

    譯者: Dreamer (http://www.zhuoqun.net)

    _______________________________________________________________________________

    處理異步事件,第一部分

    使用異步事件模型的一個困難就是很難寫出易讀的代碼。 <}0{> 這對于 AJAX 以及 Flex 應用程序都是同樣真實的道理。

    過去幾個月以來,我針對這個問題嘗試了各種各樣的方法。我認為這能幫助我漫步在曾經(jīng)嘗試的各種代碼中,并以此說明不同的方法。

    讓我們以RPC service 調用為例。假設我正在使用一個http service來獲得一個唱片的信息:

    				public function getAlbumInfo(albumId: int) : void
    		

    				{
    		

    				
    						
    						myService.request = { type: "album", albumId: albumId };
    		

    				
    						
    						myService.send();
    		

    				
    				
    		

    				
    						
    						// I'd like to do something with the results of
    		

    				
    						
    						// my request, but I can't!
    		

    				}
    		

    問題是結果并不是立刻就返回。代碼在執(zhí)行而結果可能在數(shù)百毫秒內無法返回。此外,Flash Player不提供一個阻滯的方法來等待結果就緒。為了相應最終返回的結果,你需要俘獲一個事件。

    				public function getAlbumInfo(albumId: int) : void
    		

    				{
    		

    				
    						
    						myService.addEventListener("result", getAlbumInfoResult);
    		

    				
    						
    						myService.request = { type: "album", albumId: albumId };
    		

    				
    						
    						myService.send();
    		

    				}
    		

    				
    				
    		

    				public function getAlbumInfoResult(event: Event) : void
    		

    				{
    		

    				
    						
    						// Hundreds of milliseconds later, my results
    		

    				
    						
    						// have arrived, and I can add them to my list!
    		

    				
    						
    						myAlbumList.addAlbum(event.result.album);
    		

    				}
    		

    這并不太差勁,是嗎?現(xiàn)在,想象一下現(xiàn)在我需要在結果函數(shù)中使用albumId,而恰好RPC send()方法就有一個叫做呼叫對象(call object)的特殊對象來讓我們那樣做。

    使用呼叫對象來傳遞參數(shù)

    呼叫對象是一個一旦結果事件(result event)觸發(fā)就會被傳送到結果處理程序的對象。

    				public function getAlbumInfo(albumId: int) : void
    		

    				{
    		

    				
    						
    						myService.addEventListener("result", getAlbumInfoResult);
    		

    				
    						
    						myService.request = { type: "album", albumId: albumId };
    		

    				
    				
    		

    				
    						
    						// Make the call, and save a value for later use.
    		

    				
    						
    						var call : Object = myService.send();
    		

    				
    						
    						call.albumId = albumId;
    		

    				}
    		

    				
    				
    		

    				public function getAlbumInfoResult(event: Event) : void
    		

    				{
    		

    				
    						
    						// Use the albumId value that was passed to me from above
    		

    				
    						
    						// as part of the call object.
    		

    				
    						
    						myAlbumList.addAlbum(event.call.albumId, event.result.album);
    		

    				}
    		

    現(xiàn)在,假設我需要把這些呼叫串在一起。它會變得非常凌亂不堪。

    				public function getAlbumInfo(albumId: int) : void
    		

    				{
    		

    				
    						
    						myService.addEventListener("result", getAlbumInfoResult);
    		

    				
    						
    						myService.request = { type: "album", albumId: albumId };
    		

    				
    				
    		

    				
    						
    						// Save the albumId for use later!
    		

    				
    						
    						var call : Object = myService.send();
    		

    				
    						
    						call.albumId = albumId;
    		

    				}
    		

    				
    				
    		

    				public function getAlbumInfoResult(event: Event) : void
    		

    				{
    		

    				
    						
    						var artistId: int = event.result.album.artistId;
    		

    				
    				
    		

    				
    						
    						myAlbumList.addAlbum(event.call.albumId, event.result.album);
    		

    				
    				
    		

    				
    						
    						myService.addEventListener("result", getArtistInfoResult);
    		

    				
    						
    						myService.request = { type: "artist", artistId : artistId };
    		

    				
    				
    		

    				
    						
    						// Now, save the artistId for use later!
    		

    				
    						
    						var call = myService.send();
    		

    				
    						
    						call.artistId = artistId;
    		

    				}
    		

    				
    				
    		

    				public function getArtistInfoResult(event: Event) : void
    		

    				{
    		

    				
    						
    						myArtistList.addArtist(event.call.artistId, event.result.artist);
    		

    				}
    		

    下面,讓我們假設一種更復雜的情形:如果多個呼叫程序需要調用同一個HTTP service呢?你如何確保正確地處理返回結果?

    多個呼叫的問題

    讓我們把上面的代碼做點簡單的改變來闡明這個問題。

    				public function getAlbumInfo(albumId: int) : void
    		

    				{
    		

    				
    						
    						// Wire up my result handler.
    		

    				
    						
    						myService.addEventListener("result", getAlbumInfoResult);
    		

    				
    				
    		

    				
    						
    						// Ask for the album info.
    		

    				
    						
    						myService.request = { type: "album", albumId: albumId };
    		

    				
    						
    						myService.send();
    		

    				
    				
    		

    				
    						
    						// Also ask for the album art.
    		

    				
    						
    						myService.request = { type: "albumArt", albumId: albumId };
    		

    				
    						
    						myService.send();
    		

    				}
    		

    				
    				
    		

    				public function getAlbumInfoResult(event: Event) : void
    		

    				{
    		

    				
    						
    						// At this point, I have no idea whether I should be
    		

    				
    						
    						// handling the album info or the album art.
    		

    				}
    		

    對這個問題的愚蠢的解決方法就是在第一個send之前綁定第一個函數(shù),在第二個send之前綁定第二個函數(shù):

    				public function getAlbumInfo(albumId: int) : void
    		

    				{
    		

    				
    						
    						// Wire up my result handler.
    		

    				
    						
    						myService.addEventListener("result", getAlbumInfoResult);
    		

    				
    				
    		

    				
    						
    						// Ask for the album info.
    		

    				
    						
    						myService.request = { type: "album", albumId: albumId };
    		

    				
    						
    						myService.send();
    		

    				
    				
    		

    				
    						
    						// BUG!! This will not work!
    		

    				
    						
    						myService.removeEventListener("result", getAlbumInfoResult);
    		

    				
    						
    						myService.addEventListener("result", getAlbumArtResult);
    		

    				
    				
    		

    				
    						
    						// Also ask for the album art.
    		

    				
    						
    						myService.request = { type: "albumArt", albumId: albumId };
    		

    				
    						
    						myService.send();
    		

    				}
    		

    如果你對異步編程很熟悉的話,你馬上就會明白問題在哪里。對于那些不熟悉的人,這里列出了將會發(fā)生的事件的順序:

    <!--[if !supportLists]-->1.<!--[endif]-->一個“result”的監(jiān)聽器(listener)將會綁定到getAlbumInfoResult()

    <!--[if !supportLists]-->2.<!--[endif]-->建立album info請求。

    <!--[if !supportLists]-->3.<!--[endif]-->先前的監(jiān)聽器被移除。

    <!--[if !supportLists]-->4.<!--[endif]-->result”的一個新的監(jiān)聽器被綁定到getAlbumArtResult()

    <!--[if !supportLists]-->5.<!--[endif]-->建立album art 請求。

    <!--[if !supportLists]-->6.<!--[endif]-->等待一段時間。

    <!--[if !supportLists]-->7.<!--[endif]-->由于網(wǎng)絡沒有任何規(guī)律,album info的結果返回或者是album art的結果返回。

    <!--[if !supportLists]-->8.<!--[endif]-->不管哪個呼叫返回,它都會找到getAlbumArtResult()。因為這個時候它是唯一注冊的監(jiān)聽器。

    解決多個呼叫(mutiple call)的問題

    解決多個呼叫問題的傳統(tǒng)方法就是吧callback函數(shù)附加到呼叫對象上。這樣可以正常工作,因為每次service被調用的時候一個唯一的呼叫對象就會被創(chuàng)建。

    				public function doInit()
    		

    				{
    		

    				
    						
    						
    						
    						myService.addEventListener("result", handleResult);
    		

    				}
    		

    				
    				
    		

    				public function getAlbumInfo(albumId: int) : void
    		

    				{
    		

    				
    						
    						var call : Object;
    		

    				
    				
    		

    				
    						
    						// Ask for the album info.
    		

    				
    						
    						myService.request = { type: "album", albumId: albumId };
    		

    				
    						
    						call = myService.send();
    		

    				
    						
    						
    						
    						call.handler = getAlbumInfoResult;
    		

    				
    				
    		

    				
    						
    						// Also ask for the album art.
    		

    				
    						
    						myService.request = { type: "albumArt", albumId: albumId };
    		

    				
    						
    						call = myService.send();
    		

    				
    						
    						call.handler = getAlbumArtResult;
    		

    				}
    		

    				
    				
    		

    				public function handleResult(event: ResultEvent) : void
    		

    				{
    		

    				
    						
    						// Retrieve the call object from the event.
    		

    				
    						
    						var call : Object = event.call;
    		

    				
    				
    		

    				
    						
    						// Get the handler.
    		

    				
    						
    						var handler : Function = call.handler;
    		

    				
    				
    		

    				
    						
    						// Call the handler. We use handler.call(xxx) instead
    		

    				
    						
    						// of handler(xxx) to properly deal with the scope chain.
    		

    				
    						
    						handler.call(null, event);
    		

    				}
    		

    這在個新的代碼中,兩個對service的調用會呼叫同一個處理函數(shù),但是實際上被呼叫的處理函數(shù)是隱藏在呼叫對象中的那個。在第一次呼叫的情況中,getAlbumInfoResult()將會被呼叫,而在第二種情況下,getAlbumArtResult()將會被呼叫。

    posted on 2007-02-28 19:51 ???MengChuChen 閱讀(778) 評論(0)  編輯  收藏 所屬分類: flex2.0
    主站蜘蛛池模板: 亚洲日韩中文字幕日韩在线| 久久国产精品一区免费下载| 在线免费观看一级毛片| 亚洲欧洲另类春色校园小说| 一级毛片免费毛片一级毛片免费 | 免费观看成人毛片a片2008| 精品日韩亚洲AV无码一区二区三区| 成人性做爰aaa片免费看| 久久精品国产精品亚洲精品| 免费a级毛片无码a∨免费软件| 亚洲成a人片在线观看日本| 免费无码又爽又刺激网站直播| 亚洲中文字幕不卡无码| 久久久久国产精品免费看| 亚洲va在线va天堂va四虎| 国产又大又粗又长免费视频| 久久精品国产亚洲AV久| 免费高清小黄站在线观看| 西西人体大胆免费视频| 国产国拍精品亚洲AV片| 四虎影视在线影院在线观看免费视频 | 亚洲av日韩av无码| 亚洲免费黄色网址| 午夜免费1000部| 亚洲午夜激情视频| 永久免费在线观看视频| aⅴ在线免费观看| 亚洲午夜无码久久久久软件| 国产精品免费视频播放器| 国产精品青草视频免费播放| 亚洲人成在线观看| 成年女人免费视频播放体验区| 日本亚洲中午字幕乱码| 亚洲国产精品福利片在线观看| 国产成人精品久久免费动漫| 亚洲欧洲精品成人久久曰| 国产亚洲精品无码专区| 波多野结衣在线免费观看| 黄色毛片免费在线观看| 亚洲午夜视频在线观看| 国产成人免费福利网站|