到底是何方妖怪呢?打出來看看:
所謂 Promise,就是一個對象,用來傳遞異步操作的消息。它代表了某個未來才會知道結果的事件(通常是一個異步操作),并且這個事件提供統一的 API,可供進一步處理。
Promise 對象有以下兩個特點。
(1)對象的狀態不受外界影響。Promise 對象代表一個異步操作,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和 Rejected(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態,任何其他操作都無法改變這個狀態。這也是 Promise 這個名字的由來,它的英語意思就是「承諾」,表示其他手段無法改變。
(2)一旦狀態改變,就不會再變,任何時候都可以得到這個結果。Promise 對象的狀態改變,只有兩種可能:從 Pending 變為 Resolved 和從 Pending 變為 Rejected。只要這兩種情況發生,狀態就凝固了,不會再變了,會一直保持這個結果。就算改變已經發生了,你再對 Promise 對象添加回調函數,也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監聽,是得不到結果的。
有了 Promise 對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。此外,Promise 對象提供統一的接口,使得控制異步操作更加容易。
Promise 也有一些缺點。首先,無法取消 Promise,一旦新建它就會立即執行,無法中途取消。其次,如果不設置回調函數,Promise 內部拋出的錯誤,不會反應到外部。第三,當處于 Pending 狀態時,無法得知目前進展到哪一個階段(剛剛開始還是即將完成)。
廢話不多說,直接上demo:
Promise 學習筆記
怎么樣?是不是灰常簡單啊!
demo2:
Promise 構造函數接受一個函數作為參數,該函數的兩個參數分別是 resolve 方法和 reject 方法。
如果異步操作成功,則用 resolve 方法將 Promise 對象的狀態,從「未完成」變為「成功」(即從 pending 變為 resolved);
如果異步操作失敗,則用 reject 方法將 Promise 對象的狀態,從「未完成」變為「失敗」(即從 pending 變為 rejected)。
all的用法:
demo:
Promise 學習筆記
用Promise.all來執行,all接收一個數組參數,里面的值最終都算返回Promise對象。這樣,三個異步操作的并行執行的,等到它們都執行完后才會進到then里面。那么,三個異步操作返回的數據哪里去了呢?都在then里面呢,all會把所有異步操作的結果放進一個數組中傳給then,就是上面的results。
race的用法
all方法的效果實際上是「誰跑的慢,以誰為準執行回調」,那么相對的就有另一個方法「誰跑的快,以誰為準執行回調」,這就是race方法,這個詞本來就是賽跑的意思。race的用法與all一樣,我們把上面runAsync1的延時改為1秒來看一下:
Promise 學習筆記
看到沒:只有第一個執行了回調!
在then里面的回調開始執行時,runAsync2()和runAsync3()并沒有停止,仍舊再執行。于是再過1秒后,輸出了他們結束的標志。
這個race有什么用呢?使用場景還是很多的,比如我們可以用race給某個異步請求設置超時時間,并且在超時后執行相應的操作。
再來看看jquery里面的$.Deferred:
jquery用$.Deferred實現了Promise規范,$.Deferred是個什么玩意呢?還是老方法,打印出來看看,先有個直觀印象:
var def = $.Deferred(); console.log(def);
輸出如下:
$.Deferred()返回一個對象,我們可以稱之為Deferred對象,上面掛著一些熟悉的方法如:done、fail、then等。jquery就是用這個Deferred對象來注冊異步操作的回調函數,修改并傳遞異步操作的狀態。
Deferred對象的基本用法如下,為了不與ajax混淆,我們依舊舉setTimeout的例子:
輸出“執行完成”,而是直接輸出“我穿越了”。因為我們在異步操作執行完成之前,沒等他自己resolve,就在外部給resolve了。這顯然是有風險的,比如你定義的一個異步操作并指定好回調函數,有可能被別人給提前結束掉,你的回調函數也就不能執行了。Document
怎么辦?jquery提供了一個promise方法,就在def對象上,他可以返回一個受限的Deferred對象,所謂受限就是沒有resolve、reject等方法,無法從外部來改變他的狀態,用法如下:
Document
Document
除此之外,jquery還增加了兩個語法糖方法,done和fail,分別用來指定執行完成和執行失敗的回調,也就是說這段代碼:
d.then(function(){ console.log('執行完成'); }, function(){ console.log('執行失敗'); });
與這段代碼是等價的:
d.done(function(){ console.log('執行完成'); }) .fail(function(){ console.log('執行失敗'); });
always的用法
jquery的Deferred對象上還有一個always方法,不論執行完成還是執行失敗,always都會執行,有點類似ajax中的complete。不贅述了。
$.when的用法
jquery中,還有一個$.when方法來實現Promise,與ES6中的all方法功能一樣,并行執行異步操作,在所有的異步操作執行完后才執行回調函數。不過$.when并沒有定義在$.Deferred中,看名字就知道,$.when,它是一個單獨的方法。與ES6的all的參數稍有區別,它接受的并不是數組,而是多個Deferred對象,如下:
$.when(runAsync(), runAsync2(), runAsync3()) .then(function(data1, data2, data3){ console.log('全部執行完成'); console.log(data1, data2, data3); });
jquery中沒有像ES6中的race方法嗎?就是以跑的快的為準的那個方法。對的,jquery中沒有。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com