Deferred對象

摘要:雖然js已經出了ES6,ES7等等版本,從而也誕生了新的異步對象->promise,可是基礎仍是要終結的,這一片就來回顧一下ajax以及ajax的異步對象->deferred。ajax

1.傳統ajaxapi

傳統模式$.ajax()接受參數爲一個對象,該對象包含了callback(success和error)promise

栗子:異步

 1 function toJson(data) {
 2     document.write('<pre><code>' + JSON.stringify(data) + '</code></pre>');
 3 }
 4 $.ajax({
 5     url: "http://yapi.demo.qunar.com/mock/10343/getinfo",
 6     success: function (data) {
 7         toJson(data);
 8     },
 9     error: function (error) {
10         console.log('error');
11     }
12 });

這裏安利一個第三方平臺YAPI,能夠經過YAPI模擬server端。函數

運行結果:url

2.隨着jQuery的改進,新的寫法誕生了spa

栗子:code

 1 function toJson(data) {
 2     document.write('<pre><code>' + JSON.stringify(data) + '</code></pre>');
 3 }
 4 $.ajax("http://yapi.demo.qunar.com/mock/10343/getinfo")
 5 .done(function(data){
 6     toJson(data);
 7 })
 8 .fail(function(e){
 9     console.log(e);
10 })

運行結果:server

增長了鏈式用法。這是爲啥呢。由於jQuery在1.5.0版本之後增長了deferred對象,支持了鏈式調用方式。對象

3.增長了多個延遲函數公用一個回調函數,因而$.when()誕生了。

栗子:

 1 function toJson(arr) {
 2     arr.forEach(a => {
 3         document.write('<pre><code>' + JSON.stringify(a) + '</code></pre>');
 4     })
 5 }
 6 $.when($.ajax("http://yapi.demo.qunar.com/mock/10343/getinfo"),
 7     $.ajax("http://yapi.demo.qunar.com/mock/10343/getinfo"))
 8     .done(function (data, data2) {
 9         toJson([data[0], data2[0]]);
10     })
11     .fail(function (e) {
12         console.log(e);
13     })

結果:

這裏若是兩個ajax若是其中有一個失敗則會調用fail的callback,到這裏若是異步不是ajax呢,是setTimeout呢~

栗子:

1 function wait() {
2     var delayFn = function () {
3         console.log('over.');
4     };
5     setTimeout(delayFn, 5000);
6 };

要知道執行函數wait的時候,delayFn會以一個新的宏任務重新扔到一個事件隊列裏,這時兩個函數變成爲了異步,那麼這時候出現一個新的函數,如何控制新的函數要執行與延遲函數以後呢。

方式1:講函數寫在延遲函數內,這不廢話嗎。

方式2:若是與wait在同屬一個宏任務呢?答案是利用$.when(),以微任務的形式存在。這樣等延遲函數執行完再去執行,就是咱們上面栗子3的形式了。

栗子:

 1 function wait(dtd) {
 2     console.log(new Date())
 3     var delayFn = function () {
 4     };
 5     setTimeout(delayFn, 5000);
 6 };
 7 $.when(wait())
 8     .done(function (data) {
 9         console.log(new Date());
10     })
11     .fail(function (e) {
12         console.log(e)
13     })

執行結果:

事實上並無等延遲函數執行完,才進入的回調函數,彷佛直接就執行了回調函數,這是爲啥呢?

緣由是:$.when()接受的對象必須是deferred對象,不然會當即執行回調函數。改進以下。

栗子:

 1 var dtd = $.Deferred();
 2 function wait(dtd) {
 3     console.log(new Date())
 4     var delayFn = function () {
 5         dtd.resolve();
 6     };
 7     setTimeout(delayFn, 5000);
 8     return dtd;
 9 };
10 $.when(wait(dtd))
11     .done(function (data) {
12         console.log(new Date());
13     })
14     .fail(function (e) {
15         console.log(e)
16     })

運行結果:

deferred對象此外還有兩個方法分別是:reject()、promise()

resolve:改變deferred對象的狀態,執行done callback。

reject:reject()與reslove()方法同樣,同爲改變deferred對象的狀態,當狀態爲reject時,這執行fail callback。

promise:從新生成deferred對象。

4.promise對象

我猜ES6也是根據這個詞兒誕生的promise對象,嘿嘿。

上面栗子能夠看到dtd是外部傳入的對象,在wait之外就能夠改變deferred對象狀態,直接執行回調函數

栗子:

 1 function toJson(arr) {
 2     arr.forEach(a => {
 3         document.write('<pre><code>' + JSON.stringify(a) + '</code></pre>');
 4     })
 5 }
 6 var dtd = $.Deferred();
 7 function wait(dtd) {
 8     console.log(new Date())
 9     var delayFn = function () {
10         dtd.resolve();
11     };
12     setTimeout(delayFn, 5000);
13     return dtd;
14 };
15 $.when(wait(dtd))
16     .done(function (data) {
17         console.log(new Date());
18     })
19     .fail(function (e) {
20         console.log('error' + ' time:' + new Date())
21     })
22 dtd.reject();

執行結果:

能夠看到在外面修改deferred狀態就會當即執行fail callback函數了。那麼如何避免呢~,咱們利用promise() 從新生成一個deferred對象。

 栗子:

 1 function toJson(arr) {
 2     arr.forEach(a => {
 3         document.write('<pre><code>' + JSON.stringify(a) + '</code></pre>');
 4     })
 5 }
 6 var dtd = $.Deferred();
 7 var waitDtd = function wait(dtd) {
 8     console.log(new Date())
 9     var delayFn = function () {
10         dtd.resolve();
11     };
12     setTimeout(delayFn, 5000);
13     return dtd.promise();
14 };
15 $.when(waitDtd)
16     .done(function (data) {
17         console.log(new Date());
18     })
19     .fail(function (e) {
20         console.log('error' + ' time:' + new Date())
21     })
22 waitDtd.reject();

over~

相關文章
相關標籤/搜索