首頁  >  文章  >  web前端  >  jQuery的Promise如何正確使用

jQuery的Promise如何正確使用

小云云
小云云原創
2018-01-26 10:58:302174瀏覽

關於jQuery的Promise的使用方法,大家了解多少?本文就主要和大家分享jQuery的Promise如何正確使用,希望能幫助大家。

先前了解了ES6的Promise對象,來看看jQuery中的Promise,也就是jQuery的Deferred對象。

先開啟瀏覽器的控制台。


<script>
  var defer = $.Deferred();
  console.log(defer);
</script>

運行結果:

 

和ES6的Promise物件長的有點像,jQuery的Deferred物件也有resolve 、reject、then方法,還有done、fail、always......方法。 jQuery就是用這個Deferred物件來註冊非同步操作的回呼函數,修改並傳遞非同步操作的狀態。

玩玩Deferred:


<script>
  function runAsync(){
    var defer = $.Deferred();
    //做一些异步操作
    setTimeout(function(){
      console.log(&#39;执行完成&#39;);
      defer.resolve(&#39;异步请求成功之后返回的数据&#39;);
    }, 1000);
    return defer;
  }
  runAsync().then(function(data){
    console.log(data)
  });
</script>

運行之後,Deferred物件的實例defer透過resolve方法把參數「非同步請求成功之後傳回的資料」傳回到then方法中進行接收,,列印。

和ES6的Promise相似,但是有一點點區別,再看下Promise:


<script>
  function runAsync(){
    var p = new Promise(function(resolve, reject){
      
      setTimeout(function(){
        console.log(&#39;执行完成&#39;);
        resolve(&#39;异步请求成功之后返回的数据&#39;);
      }, 1000);
    });
    return p;      
  }

  runAsync().then(function(data){
    console.log(data);
  });
</script>

我們發現:

##1、創建Deferred物件的時候沒有傳參;而創建Promise物件的時候,傳了參數(傳了一個匿名函數,函數也有兩個參數:resolve、reject);

2、Deferred物件直接呼叫了resolve方法;而Promise物件則是在內部呼叫的resolve方法;

說明:Deferred物件本身就有resolve方法,而Promise物件是在構造器中透過執行resolve方法,給Promise物件賦上了執行結果的狀態。

這樣就有一個弊端:因為Deferred物件自帶resolve方法,拿到Deferred物件之後,就可以隨時呼叫resolve方法,其狀態可以進行手動幹預了


<script>
  function runAsync(){
    var defer = $.Deferred();
    //做一些异步操作
    setTimeout(function(){
      console.log(&#39;执行完成&#39;);
      defer.resolve(&#39;异步请求成功之后返回的数据&#39;);
    }, 1000);
    return defer;
  }
   var der = runAsync();
   der.then(function(data){
    console.log(data)
   });
   der.resolve(&#39;在外部结束&#39;); 
</script>

 這樣的話就直接在外部直接給Deferred設置了狀態,打印“在外部結束”,1s後打印“執行完成”,不會打印“非同步請求成功之後返回的數據”了。

顯然,這不好。我發個非同步請求,還沒收到資料就讓人在外部給我結束了。 。 。 。 。 。 。

當然這個坑jQuery一定會填的,在Deferred物件上有一個promise方法,是一個受限的Deferred物件


<script>
  function runAsync(){
    var def = $.Deferred();
    //做一些异步操作
    setTimeout(function(){
      console.log(&#39;执行完成&#39;);
      def.resolve(&#39;请求成功之后返回的数据&#39;);
    }, 2000);
    return def.promise(); //就在这里调用
  }
</script>

所謂受限的Deferred對象,就是沒有resolve和reject方法的Deferred對象。這樣就無法在外邊改變Deferred物件的狀態了。

Deferred物件的then方法和done、fail語法糖

我們知道,在ES6的Promise規範中,then方法接受兩個參數,分別是執行完成和執行失敗的回調,而jquery中進行了增強,還可以接受第三個參數,就是在pending狀態時的回調,如下:

deferred.then( doneFilter [, failFilter ] [ , progressFilter ] )

then方法:


#

<script>
  function runAsync(){
    var def = $.Deferred();
    //做一些异步操作
    setTimeout(function(){
       var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num<=5){
          def.resolve(num);
        }
        else{
          def.reject(&#39;数字太大了&#39;);
        }
    }, 2000);
    return def.promise(); //就在这里调用
  }

  runAsync().then(function(d){
    console.log("resolve");
    console.log(d);
  },function(d){
    console.log("reject");
    console.log(d);
  })

</script>

Deferred物件的then方法也是可以進行鍊式運算的。

done,fail語法糖,分別用來指定執行完成和執行失敗的回呼,與這段程式碼是等價的:


<script>
  function runAsync(){
    var def = $.Deferred();
    //做一些异步操作
    setTimeout(function(){
       var num = Math.ceil(Math.random()*10); //生成1-10的随机数
        if(num<=5){
          def.resolve(num);
        }
        else{
          def.reject(&#39;数字太大了&#39;);
        }
    }, 2000);
    return def.promise(); //就在这里调用
  }

  runAsync().done(function(d){
    console.log("resolve");
    console.log(d);
  }).fail(function(d){
    console.log("reject");
    console.log(d);
  })

</script>

always的用法

jquery的Deferred物件上還有一個always方法,不論執行完成還是執行失敗,always都會執行,有點類似ajax中的complete。

$.when的用法

jquery中,還有一個$.when方法來實作Promise,與ES6中的all方法功能一樣,並行執行非同步操作,在所有的非同步操作執行完後才執行回呼函數。不過$.when並沒有定義在$.Deferred中,看名字就知道,$.when,它是一個單獨的方法。與ES6的all的參數稍有區別,它接受的並不是數組,而是多個Deferred對象,如下:


<script>
 function runAsync(){
    var def = $.Deferred();
    //做一些异步操作
    setTimeout(function(){
       var num = Math.ceil(Math.random()*10); //生成1-10的随机数
       def.resolve(num);  
    }, 2000);
    return def.promise(); //就在这里调用
  }
  $.when(runAsync(), runAsync(), runAsync()) .then(function(data1, data2, data3){
     console.log(&#39;全部执行完成&#39;);
     console.log(data1, data2, data3);
  });
</script>

jquery中沒有像ES6中的race方法嗎?就是以跑的快的為準的那個方法。對的,jquery中沒有。

以上就是jquery中Deferred物件的常用方法了。

在上一篇和本篇當中,都是用一次性定時器來取代了非同步請求進行資料處理。為什麼沒用ajax呢,不是因為麻煩,在這裡要說一下ajax和Deferred的聯繫:

jquery的ajax返回一個受限的Deferred對象,也就是沒有resolve方法和reject方法,不能從外部改變狀態,既然是Deferred對象,那麼我們上面講到的所有特性,ajax也都是可以用的。例如鍊式調用,連續發送多個請求:


<script>
req1 = function(){
  return $.ajax(/* **** */);
}
req2 = function(){
  return $.ajax(/* **** */);
}
req3 = function(){ 
  return $.ajax(/* **** */);
}
req1().then(req2).then(req3).done(function(){ console.log(&#39;请求发送完毕&#39;); });
</script>

#success、error與complete

這三個方法是我們常用的ajax語法糖。


$.ajax(/*...*/)
.success(function(){/*...*/})
.error(function(){/*...*/})
.complete(function(){/*...*/})

有時候比較喜歡在內部作為屬性來處理。

分別表示ajax請求成功、失敗、結束的回呼。這三個方法與Deferred又是什麼關係呢?其實就是語法糖,success對應done,error對應fail,complete對應always,就這樣,只是為了與ajax的參數名字上保持一致而已。

總結:

$.Deferred實作了Promise規範,then、done、fail、always是Deferred物件的方法。 $.when是一個全域的方法,用來並行執行多個非同步任務,與ES6的all是一個功能。 ajax回傳一個受限的Deferred對象,success、error、complete是ajax提供的語法糖,功能與Deferred對象的done、fail、always一致。

相關建議:

promsie.all和promise順序執行詳解

JS 中使用Promise 實作紅綠燈實例碼( demo)

關於promise物件的簡單用法

以上是jQuery的Promise如何正確使用的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn