免费体验120秒视频_榴莲榴莲榴莲榴莲官网_2021国产麻豆剧果冻传媒入口_一二三四视频社区在线
當前位置:首頁文章首頁 IT學院 IT技術

Javascript的回調機制的經典教程

作者:  來源:  發布時間:2011-6-6 10:17:59  點擊:
  30. return 0;

  31.}

  32.//}}}

  例 5中有兩個版本,get_data_v5a假設了通信機制可以透傳a和b兩個參數給回調函數,get_data_v5b則使用了兩個全局變量來傳遞處理結 果所需的參數。兩個都不見得是很好的方法,get_data_v5a的問題是,異步通信的機制不見得能提供這種透傳機制,除非程序員自己封裝;即使程序員 自己封裝,那也意味著如果要實現多個處理數據的過程(像get_data)那就要實現多個異步調用的過程(send_and_recv_async),代 碼復雜且復用性差不好維護。而全局變量的版本也好不到哪里去,使用這種全局的機制,意味著不必要的信息暴露,也就有被別的地方錯修改的問題,同時這個函數 還變成不可重入的。即使將全局機制封裝在一個類里面,每次初始化一個對象,可以改善依然不能解決信息暴露的問題,同時還帶來了管理這多個對象的復雜性。

  

  兩種方法相比而言,貌似透傳的機制要稍好一些。我們對get_data_v5a略做修改,使得它通信過程能夠有更廣泛的復用。

  

  例6 使用一個closure對象打包過程中的參數

  view plaincopy to clipboardprint?

  01.//{{{get_data_v6

  02.// 為了統一回調函數的形式并且縮短回調的參數列表,將這種需要透傳的參數只有一個

  03.// 統一的數據結構打包

  04.void get_data_v6(int a, int b)

  05.{

  06. // 準備數據

  07. char bufCmd[]="cmd=1001&uin=123456?m=abc";

  08. char bufRcv[4096];

  09. // 打包處理結果所需要的參數

  10. closure.a = a;

  11. closure.b = b;

  12. // 通信

  13. send_and_recv_async(addr, bufCmd, bufRcv, callback, closure);

  14.} // end of get_data_v6

  15.// 回調函數的定義

  16.int callback(char* bufRcv, struct closure) {

  17. // 處理結果

  18. use(bufRcv, closure.a, closure.b);

  19. return 0;

  20.}

  21.//}}}

  例 6里面使用了一個叫closure的結構,假設這個結構是個通用的數據容器,可以容納我們使用的個中類型的任意數量的參數。增加了這一個萬能的數據容器參 數以后,異步通信過程只要能透傳這么一個數據容器就能夠很好支持個中各樣的參數透傳的需求。這個數據容器由于是在get_data函數內部產生的局部變 量,不會污染全局數據或者比get_data更大的作用域。這種受限的可見性不僅提高了代碼的可維護性,還恢復了函數的可重入性。

  

  至此我 們關于回調機制的實現的假想代碼可以說已經達到比較優雅的程度了,僅僅還有一朵小烏云。那就是我們忽略了C/C++語言里面并沒有原生實現這個超級結構, 同樣我們依然還有一點點麻煩就是還需要指定要透傳的參數。考慮到原本從準備數據到通信再到處理結果是一個完整統一的過程,原本不需要區分什么數據是前半端 使用的什么數據是后半段使用的,只要腳氣怎么治療讓前半端和后半段共享一個上下文在大部分情況下就能滿足需求了。所以現實情況下我們只能做一些妥協,使用個中折衷方案 來使得程序能運行起來。同樣,考慮到回調函數和啟動函數的關系,給回調函數命名也不是那么優雅的事情,因為畢竟它們只是同一個過程的兩半,卻要使用兩個名 字,合理一點就應該叫get_data_first和get_data_second,或者get_data_trigger和 get_data_result_handler。如果接口多的話,就會有很多這種某過程first和某過程second,或者某過程trigger和某 過程result_handler。能不能某過程就象同步那樣使用一個名字呢?我們的設想真的就沒有辦法達到嗎?答案是否定的,在Javascript能 夠幫助我們實現我們所有的設想。見例7。

  

  例7 Javascript的異步調用

  view plaincopy to clipboardprint?

  01.//{{{get_data_js

  02.//

  03.// 寫成Javascript代碼就變成現在這個樣子

  04.// url對應之前的addr

  05.// 使用匿名函數代替原來命名的callback定義

  06.// 原生支持閉包closure

  07.//

  08.function get_data_js(a, b)

  09.{

  10. var bufCmd = "cmd=1001&uin=123456?m=abc";

  11. var bufRcv;

  12. send_and_recv_with_xhr(/*addr*/url, bufCmd, bufRcv, /*callback*/

  13. function(bufRcv/*, closure*/) {

  14. use(bufRcv, /*closure.*/a, /*closure.*/b);

  15. return 0;

  16. }

  17. );

  18.}

  19.//}}}

  例 7是使用Javascript實現類似例6的功能,僅僅存在一些細微的差別。例6的場景下可能更多使用TCP或者UDP作為通信協議,而在例7使用的則是 瀏覽器提供的XHR對象實現的HTTP協議。這點差別并不會影響我們對于異步通信下回調函數實現機制的討論,只要他們的通信機制都是異步的就可以了。例7 中使用注釋的形式標注了例6里面使用的一些參數的名字以暗示它們的對應關系,方便比較這兩個例子。我們看到了,在Javascript里面我們所有的設想 都變成了現實。(1)首先關于能夠透傳一切的超級結構,Javascript中實現了閉包的機制,保證了在這種內部的函數對象可以訪問到定義它的環境能訪 問到的所有數據,也就是在例7中的匿名回調函數可以訪問到get_data_js中能訪問到的所有數據。當然,這里重要的是局部數據,如a和b。如果是全 局數據的話左旋肉堿真的有用嗎并不需要通過閉包也能訪問到。而且這個過程是Javascript的運行環境提供的,對于程序員是透明的,程序員并不需要指定哪些參數需要透 傳。(2)不需要再為回調函數命名,因為Javascript支持匿名函數的定義,可以像定義變量一樣定義函數。而這個最終導致了我們在使用異步通信機制 的時候和使用同步的通信機制及其接近,沒有多余的名字,沒有不必要的可見性。

文章評論

軟件按字母排列: A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
免费体验120秒视频_榴莲榴莲榴莲榴莲官网_2021国产麻豆剧果冻传媒入口_一二三四视频社区在线
主站蜘蛛池模板: 人人妻人人澡人人爽欧美一区| 免费超爽大片黄| 好硬好湿好爽再深一点h视频| 曰本女同互慰高清在线观看| 国产伦精品一区二区三区| 欧美换爱交换乱理伦片试看| 真实国产乱子伦对白视频37p| 色屁屁影视大全| 国产伦一区二区三区高清| free性熟女妓女tube| 日本乱子伦xxxx少妇| 好男人在线社区www| 人妻av综合天堂一区| 香蕉99国内自产自拍视频| 国产一级毛片网站| 亚洲精品视频免费看| 亚洲欧美系列| 欧美亚洲一区二区三区| 试看120秒做受小视频免费| 伦之荡艳岳| 人人干人人干人人干| 国产激情久久久久影院| 午夜亚洲av日韩av无码大全| 亚洲av无码久久寂寞少妇| 一本色综合网久久| 久久精品国产久精国产| 亚洲精品第二页| 亚洲网站大全| 亚洲美女视频一区| 国产亚洲情侣久久精品| 色综合精品| 亚洲一区爱区精品无码| 麻豆AV一区二区三区久久| 无码人妻精品一二三区免费 | 蜜臀久久99精品久久久久久| 国产大片黄在线观看| 国产妇女馒头高清泬20p多| 免费一级毛片在线播放视频| 欧美爽爽爽爽爽爽视频| 国产在线91精品天天更新| 欧美交换乱理伦片120秒|