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