Javascript 異步編程的4種方法

? ? ? 你可能知道,Javascript語言的執行環境是"單線程"(single thread)。

  所謂"單線程",就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執行后面一個任務,以此類推。

這種模式的好處是實現起來比較簡單,執行環境相對單純;壞處是只要有一個任務耗時很長,后面的任務都必須排隊等著,會拖延整個程序的執行。常見的瀏 覽器無響應(假死),往往就是因為某一段Javascript代碼長時間運行(比如死循環),導致整個頁面卡在這個地方,其他任務無法執行。

  為了解決這個問題,Javascript語言將任務的執行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。

  "同步模式"就是上一段的模式,后一個任務等待前一個任務結束,然后再執行,程序的執行順序與任務的排列順序是一致的、同步的;"異步模式"則 完全不同,每一個任務有一個或多個回調函數(callback),前一個任務結束后,不是執行后一個任務,而是執行回調函數,后一個任務則是不等前一個任 務結束就執行,所以程序的執行順序與任務的排列順序是不一致的、異步的。

 "異步模式"非常重要。在瀏覽器端,耗時很長的操作都應該異步執行,避免瀏覽器失去響應,最好的例子就是Ajax操作。在服務器端,"異步模式"甚至是唯一的模式,因為執行環境是單線程的,如果允許同步執行所有http請求,服務器性能會急劇下降,很快就會失去響應。

  本文總結了"異步模式"編程的4種方法,理解它們可以讓你寫出結構更合理、性能更出色、維護更方便的Javascript程序。

  一、回調函數

  這是異步編程最基本的方法。

  假定有兩個函數f1和f2,后者等待前者的執行結果。

f1();
f2(); 

  如果f1是一個很耗時的任務,可以考慮改寫f1,把f2寫成f1的回調函數。

function f1(callback){setTimeout(function () {// f1的任務代碼callback();}, 1000);
} 

  執行代碼就變成下面這樣:

f1(f2); 

  采用這種方式,我們把同步操作變成了異步操作,f1不會堵塞程序運行,相當于先執行程序的主要邏輯,將耗時的操作推遲執行。

  回調函數的優點是簡單、容易理解和部署,缺點是不利于代碼的閱讀和維護,程序的流程會很混亂,而且每個任務只能指定一個回調函數。

  二、事件監聽

  另一種思路是采用事件驅動模式。任務的執行不取決于代碼的順序,而取決于某個事件是否發生。

  還是以f1和f2為例。首先,為f1綁定一個事件(這里采用的jQuery的寫法)。

f1.on('done',f2); 

  上面這行代碼的意思是,當f1發生done事件,就執行f2。然后,對f1進行改寫:

function f1(){setTimeout(function () {// f1的任務代碼f1.trigger('done');}, 1000);
} 

  f1.trigger('done')表示,執行完成后,立即觸發done事件,從而開始執行f2。

  這種方法的優點是比較容易理解,可以綁定多個事件,每個事件可以指定多個回調函數。缺點是整個程序都要變成事件驅動型,運行流程會變得很不清晰。

  三、發布/訂閱

  上一節的"事件",完全可以理解成"信號"。

  我們假定,存在一個"信號中心",某個任務執行完成,就向信號中心"發布"(publish)一個信號,其他任務可以向信號中心"訂閱"(subscribe)這個信號,從而知道什么時候自己可以開始執行。這就叫做"發布/訂閱模式"(publish-subscribe pattern),又稱"觀察者模式"(observer pattern)。

  這個模式有多種實現,下面采用的是Ben Alman的Tiny Pub/Sub,這是jQuery的一個插件。

  首先,f2向"信號中心"jQuery訂閱"done"信號。

jQuery.subscribe("done", f2); 

  然后,f1進行如下改寫:

function f1(){setTimeout(function () {// f1的任務代碼jQuery.publish("done");}, 1000);
} 

  jQuery.publish("done")的意思是,f1執行完成后,向"信號中心"jQuery發布"done"信號,從而引發f2的執行。

  此外,f2完成執行后,也可以取消訂閱(unsubscribe)。

jQuery.unsubscribe("done", f2); 

  這種方法的性質與"事件監聽"類似,但是明顯優于后者。因為我們可以通過查看"消息中心",了解存在多少信號、每個信號有多少訂閱者,從而監控程序的運行。

  四、Promises對象

  Promises對象是CommonJS工作組提出的一種規范,目的是為異步編程提供統一接口。

  簡單說,它的思想是,每一個異步任務返回一個Promise對象,該對象有一個then方法,允許指定回調函數。比如,f1的回調函數f2,可以寫成:

f1().then(f2); 

  f1要進行如下改寫(這里使用的是jQuery的實現):

function f1(){var dfd = $.Deferred();setTimeout(function () {// f1的任務代碼dfd.resolve();}, 500);return dfd.promise;
} 

  這樣寫的優點在于,回調函數變成了鏈式寫法,程序的流程可以看得很清楚,而且有一整套的配套方法,可以實現許多強大的功能。

  比如,指定多個回調函數:

f1().then(f2).then(f3); 

  再比如,指定發生錯誤時的回調函數:

f1().then(f2).fail(f3); 

  而且,它還有一個前面三種方法都沒有的好處:如果一個任務已經完成,再添加回調函數,該回調函數會立即執行。所以,你不用擔心是否錯過了某個事件或信號。這種方法的缺點就是編寫和理解,都相對比較難。

  五、參考鏈接

  * Asynchronous JS: Callbacks, Listeners, Control Flow Libs and Promises

?

?

? ?轉自(http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html)

轉載于:https://www.cnblogs.com/wuxiang/p/4772292.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374565.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374565.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374565.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

力扣奇偶鏈表

給定單鏈表的頭節點 head ,將所有索引為奇數的節點和索引為偶數的節點分別組合在一起,然后返回重新排序的列表。 第一個節點的索引被認為是 奇數 , 第二個節點的索引為 偶數 ,以此類推。 請注意,偶數組和奇數組內部的…

JAVA入門之方法

所謂方法,就是用來解決一類問題的代碼的有序組合,是一個功能模塊。 一般情況下,定義一個方法的語法是: 其中: 1、 訪問修飾符:方法允許被訪問的權限范圍, 可以是 public、protected、private 甚…

使用Netbeans開發App Engine Java

如果您剛開始進行App引擎開發,那么您可能會感覺Eclipse是首選的IDE。 而且,Google還單獨提供了它的Eclipse IDE 官方插件 。 但是不使用Eclipse的人呢? 當然,您始終可以進行命令行開發,但是現在這些人是誰!…

JAVA基本類庫介紹

我們曾經講過,Java已經為編程者編制了許多類,這些類已經經過測試,基本上不存在錯誤,這些類都是我們編程的基礎。如果不利用這些已存在的類,我們的 編程工作將變得異常復雜,所以我們應盡可能多的掌握Java基本…

力扣回文鏈表

給你一個單鏈表的頭節點 head &#xff0c;請你判斷該鏈表是否為回文鏈表。如果是&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。 class Solution {public boolean isPalindrome(ListNode head) {List<Integer> res new ArrayList<Integer>()…

JAVA運算符和優先級

1、算術運算符&#xff1a; 和 -- 既可以出現在操作數的左邊&#xff0c;也可以出現在右邊&#xff0c;但結果是不同&#xff0c;如&#xff1a; ①int a5&#xff1b;int ba&#xff1b; #先把a賦給b&#xff0c;a再自增 ②int a5&#xff1b;int ba&#xff1b;   #a先…

將JSON功能添加到您的GWT應用程序中

JSON簡介 在Web應用程序上工作時&#xff0c;總是會出現客戶端-服務器數據交換的問題。 在此問題上有多種方法&#xff0c;其中許多使用XML進行交換。 執行此任務的一種不太知名的格式是JSON。 JSON&#xff08;JavaScript對象表示法&#xff09;是一種輕量級的數據交換格式。…

win10資源管理器怎么打開_讓你效率倍增的電腦神器,最強資源管理器增強工具「QTTabBar」...

前言Windows 自帶的資源管理器的功能比較簡單&#xff0c;夠用是夠用了&#xff0c;但有時也確實無法滿足我們對更便捷高效的操作方式的追求。「QTTabBar」正是一個非常強大的 Windows 資源管理器增強工具&#xff01;不僅支持多標簽頁管理&#xff0c;還有許多便捷的擴展功能&…

android橫向滑動選擇的view

做文字編輯&#xff0c;從網上找來的。 HorizontalScrollSelectView&#xff1a; public boolean mAlwaysOverrideTouch true;protected ListAdapter mAdapter;private int mLeftViewIndex -1;private int mRightViewIndex 0;protected int mCurrentX;protected int mNextX;…

適用于Mac OS X的官方Java 7 –狀態

希望到現在&#xff0c;每個人都知道蘋果公司去年加入了OpenJDK項目。 這意味著什么&#xff1f; 蘋果將??把用于私有Mac Java構建的代碼作為GPL代碼貢獻給OpenJDK 甲骨文將接管Java的Mac端口 隨著時間的流逝&#xff0c;Mac平臺將成為Java世界中完全一流的公民 對于想要在…

excel使用教程_數據分析Excel必備技能:數據透視表使用教程

江米小棗tonylua | 作者掘金 | 來源處理數量較大的數據時&#xff0c;一般分為數據獲取、數據篩選&#xff0c;以及結果展示幾個步驟。在 Excel 中&#xff0c;我們可以利用數據透視表(Pivot Table)方便快捷的實現這些工作。本文首先手把手的教你如何在 Excel 中手動構建一個基…

.典型用戶 - 場景

典型用戶&#xff1a; 名字黃德勝性別、年齡男&#xff0c;35歲職業自由投資人收入20萬元/年知識層次和能力專科&#xff0c;有一定的投資經驗&#xff0c;對經濟有自己的看法生活/工作情況已婚&#xff0c;生活負擔在加重動機&#xff0c;目的&#xff0c;困難想要增加收入&am…

java調用webservice_篤學私教:Java開發網站架構演變過程-從單體應用到微服務架構詳解...

原標題&#xff1a;篤學私教&#xff1a;Java開發網站架構演變過程-從單體應用到微服務架構詳解Java開發網站架構演變過程&#xff0c;到目前為止&#xff0c;大致分為5個階段&#xff0c;分別為單體架構、集群架構、分布式架構、SOA架構和微服務架構。下面玄武老師來給大家詳細…

再把你的錢加倍

總覽 很久以前&#xff0c;我寫了一篇關于用雙倍賺錢的文章。 但是&#xff0c;當解決方案相當簡單時&#xff0c;仍然是許多開發人員普遍擔心的問題。 用雙倍賺錢的問題 double有兩種類型的錯誤。 它存在表示錯誤。 即&#xff0c;它不能完全代表所有可能的十進制值。 即使0…

單元測試中Assert類的用法

Assert類所在的命名空間為Microsoft.VisualStudio.TestTools.UnitTesting 在工程文件中只要引用Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll就可以使用了&#xff0c; 在這里我會舉例說明Assert里面的一些主要的靜態成員。 1、 AreEqual&#xff1a;方法被重載…

CocoaPods安裝使用

$ gem sources --remove https://rubygems.org/ //等有反應之后再敲入以下命令 $ gem sources -a http://ruby.taobao.org/*** CURRENT SOURCES ***http://ruby.taobao.org/ //出現這個說明安裝正確$ sudo gem install cocoapods 安裝cocoaPods到項目的路徑下 $ touch Pod…

303. 區域和檢索 - 數組不可變(數組前綴和知識應用)

給定一個整數數組 nums&#xff0c;處理以下類型的多個查詢: 計算索引 left 和 right &#xff08;包含 left 和 right&#xff09;之間的 nums 元素的 和 &#xff0c;其中 left < right 實現 NumArray 類&#xff1a; NumArray(int[] nums) 使用數組 nums 初始化對象 in…

pat1049. Counting Ones (30)

1049. Counting Ones (30) 時間限制10 ms內存限制65536 kB代碼長度限制16000 B判題程序Standard作者CHEN, YueThe task is simple: given any positive integer N, you are supposed to count the total number of 1s in the decimal form of the integers from 1 to N. For ex…

加油站會員管理系統源碼php_加油站使用會員管理系統,如何解決行業瓶頸?

隨著人們生活條件的不斷改善&#xff0c;基本上家家戶戶都有了私家車輛&#xff0c;這對于加油站而言&#xff0c;覆蓋的客戶量也逐漸增多。現在很多加油站還是處于比較傳統的收銀模式和會員營銷管理模式&#xff0c;收銀效率低&#xff0c;客戶得不到全方面的管理。尤其是在高…

專2-第二課 Eclipse開發環境搭建

2.1下載Eclipse 2.2 安裝C/C版本的Eclipse 2.3 安裝JDT插件開發Java程序 2.4 使用Eclipse開發驅動程序 既然安裝了eclipse來進行驅動學習&#xff0c;那么我們就先來試試看eclipse開發驅動的大致流程。這里以Linux設備驅動作為示列給讀者展示整個流程&#xff0c;Android底層的…