Promise
用於對異步操做的進行數據處理,爲異步操做的回調函數提供接口,讓其在可同步執行,而不用再將回調函數進行層層嵌套。
例如,咱們如下面的例子爲例:javascript
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index</title> </head> <body> <div id="app"></div> <template id="template"> <p></p> </template> </body> <script type="text/javascript"> var app = document.querySelector('#app'); var p = document.getElementById('template').content.querySelector('p'); var p1 = p.cloneNode(true); var p2 = p.cloneNode(true); var p3 = p.cloneNode(true); var i = 0, html; window.setTimeout(() => { p1.innerHTML = '<p>aaaaaaaa</p>'; app.appendChild(p1); }, 100); window.setTimeout(() => { p2.innerHTML = '<p>bbbbbbbb</p>'; app.appendChild(p2); }, 200); window.setTimeout(() => { p3.innerHTML = '<p>cccccccc</p>'; app.appendChild(p3); }, 50); </script> </html>
對於異步函數,若是不進行回調函數嵌套,咱們就沒法保證其執行順序。可是有了Promise
對象以後,咱們能夠進行鏈式書寫,從而保證回調執行的順序。php
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Index</title> </head> <body> <div id="app"></div> <template id="template"> <p></p> </template> </body> <script type="text/javascript"> var app = document.querySelector('#app'); var p = document.getElementById('template').content.querySelector('p'); var p1 = p.cloneNode(true); var p2 = p.cloneNode(true); var p3 = p.cloneNode(true); var i = 0, html; var promise1 = new Promise((resolve, reject) => { window.setTimeout(() => { p1.innerHTML = '<p>aaaaaaaa</p>'; resolve(p1, promise2); }, 100); }); var promise2 = new Promise((resolve, reject) => { window.setTimeout(() => { p2.innerHTML = '<p>bbbbbbbb</p>'; resolve(p2, promise3); }, 200); }); var promise3 = new Promise((resolve, reject) => { window.setTimeout(() => { p3.innerHTML = '<p>cccccccc</p>'; resolve(p3, null); }, 50); }); promise1.then((node) => { app.appendChild(node); return promise2; }).then((node) => { app.appendChild(node); return promise3; }).then((node) => { app.appendChild(node); }); </script> </html>
Promise
對象是一個代理對象(代理一個值),被代理的值在Promise
對象建立時多是未知的。它容許你爲異步操做的成功和失敗分別綁定相應的處理方法(handlers
)。 這讓異步方法能夠像同步方法那樣返回值,但並非當即返回最終執行結果,而是一個能表明將來出現的結果的promise
對象。html
根據以上描述,咱們能夠知道,Promise
對象能夠代理一個異步處理的結果。因此Promise有fulfilled
(已成功)狀態和rejected
(已失敗)兩個狀態,對應Promise
構造函數的兩個回調函數:resolve
和reject
。java
new Promise( function(resolve, reject) {...} /* executor */ );
在執行回調函數以前,Promise
的狀態爲pedding
,當執行resolve
後狀態變爲fulfilled
,執行reject
以後裝態變爲rejected
。node
原型方法:jquery
//添加一個拒絕(rejection) 回調到當前 promise, 返回一個新的promise。 Promise.prototype.catch(onRejected) //添加一個拒絕(rejection) 回調到當前 promise, 返回一個新的promise。當這個回調函數被調用,新 promise 將以它的返回值來resolve,不然若是當前promise 進入fulfilled狀態,則以當前promise的完成結果做爲新promise的完成結果. Promise.prototype.then(onFulfilled, onRejected) //不管當前promise的狀態是完成(fulfilled)仍是失敗(rejected),都會執行 Promise.prototype.finally(onFinally)
Jquery中的deferred
對象是原生Promise
接口的實現。用法大同小異。ajax
在ajax
中咱們能夠直接使用,由於1.5版本以後,ajax返回的值就是一個defeered
對象。promise
舊的寫法:app
$.ajax({ url: "test.html", success: function(){ alert("成功了!"); }, error:function(){ alert("出錯啦!"); } });
新的寫法:異步
//更簡潔的鏈式寫法 $.ajax("test.html") .done(function(){ alert("成功了!"); }) .fail(function(){ alert("出錯啦!"); });
並且deferred
對象不單單是在ajax中使用,也能夠在任何回調中進行使用。
好比:
var $dfd = $.Deferred();//建立一個deferred實例對象 var success = 0;//模擬成功失敗狀態 window.setTimeout(() => { if(success === 0){ $dfd.resolve(); }else{ $dfd.reject(); } }, 100); //兩種寫法: $dfd.done(function(){ alert('成功'); }).fail(function(){ alert('失敗'); }); //------另外一種寫法 $dfd.then(function(){ alert('成功'); },function(){ alert('失敗'); });
一樣的道理,使用deferred
對象重寫書寫上面的案例:
<head> <meta charset="utf-8"> <title>Index</title> <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script> </head> <body> <div id="app"></div> <template id="template"> <p></p> </template> </body> <script type="text/javascript"> var app = $('#app'); var p = $('#template')[0].content.querySelector('p'); var p1 = p.cloneNode(true); var p2 = p.cloneNode(true); var p3 = p.cloneNode(true); var i = 0, html; var dfd1 = $.Deferred(), dfd2 = $.Deferred(), dfd3 = $.Deferred(); window.setTimeout(() => { p1.innerHTML = '<p>aaaaaaaa</p>'; dfd1.resolve(); }, 100); window.setTimeout(() => { p2.innerHTML = '<p>bbbbbbbb</p>'; dfd2.resolve(); }, 200); window.setTimeout(() => { p3.innerHTML = '<p>cccccccc</p>'; dfd3.resolve(); }, 50); dfd1.done(function(){ app.append(p1); return dfd2; }).done(function(){ app.append(p2); return dfd3; }).done(function(){ app.append(p3); }); </script> </html>
另外:jquery還提供了一個同時監聽多個回調的方法。$.when()
,返回值爲defferred
對象。
$.when()接受多個deferred對象做爲參數,當它們所有運行成功後,才調用resolved狀態的回調函數,但只要其中有一個失敗,就調用rejected狀態的回調函數。它至關於將多個非同步操做,合併成一個。實質上,when方法爲多個deferred對象,返回一個單一的promise對象。
$.when( $.ajax( "/main.php" ), $.ajax( "/modules.php" ), $.ajax( "/lists.php" ) ).then(successFunc, failureFunc);
https://wangdoc.com/javascript/async/promise.html
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises
http://javascript.ruanyifeng.com/jquery/deferred.html#toc0