精准猎取科技资讯,天堂视频在线观看,高效阅读科技新闻_黄色av网站在线免费观看_科技猎

jQuery 中的 Deferred 和 Promises (2)

我是創始人李巖:很抱歉!給自己產品做個廣告,點擊進來看看。  

看前首先了解:Promises/A規范,具體可以看這里,http://www.css88.com/archives/4743

由于jQuery版本問題對Deferred對象的實現有所不同,具體請參照jQuery api;

jQuery.Deferred()基于Promises/A規范實現,因為jQuery本身的設計風格,jQuery.Deferred()并沒有完全遵循Promises/A規范。

jQuery在1.5版本中首次引入了Deferred。你可以通過jQuery.Deferred() 在未來某個時候 得到 ‘延時’返回值。 在此之前是無法單獨使用的,Deferred作為對ajax模塊較大重寫的一部分添加進來。1.5和1.6版本包含deferred功能,可以使$.ajax() 接收調用完成及請求出錯的回調,但卻存在嚴重的耦合。新版本的jQuery提供了一些增強的方式來管理回調,提供更加靈活的方式建立回調,而不用關心原始的回調是否已經觸發。 jQuery的Deferred對象支持多個回調綁定多個任務,任務本身既可以是同步也可以是異步的。

舉個簡單地例子,原來我們寫異步的ajax請求是這么寫:

從 jQuery 1.5 開始,$.ajax()返回的jqXHR對象 實現了 Promise 接口, 使它擁有了 Promise 的所有屬性,方法和行為。(見Deferred object獲取更多信息)。為了讓回調函數的名字統一,便于在$.ajax()中使用。jqXHR也提供.error() .success()和.complete()方法。所以我們可以這樣寫:

或者這樣寫:

jQuery.Deferred對象:

了解jQuery.Deferred對象可以看下面這個表格。

jQuery.Deferred()

創建一個新的Deferred對象的構造函數,可以帶一個可選的函數參數,它會在構造完成后被調用。

jQuery.when()

通過該方式來執行基于一個或多個表示異步任務的對象上的回調函數

jQuery.ajax() 執行異步Ajax請求,返回實現了promise接口的jqXHR對象
deferred.then( doneFilter [, failFilter ] [, progressFilter ] ) 當Deferred(延遲)對象解決,拒絕或仍在進行中時,調用添加處理程序。
deferred.done() 當延遲成功時調用一個函數或者數組函數.
deferred.fail() 當延遲失敗時調用一個函數或者數組函數.。
deferred.always() 當Deferred(延遲)對象解決或拒絕時,調用添加處理程序。
deferred.resolve(ARG1,ARG2,…) 調用Deferred對象注冊的‘done’回調函數并傳遞參數
deferred.resolveWith(context,args) 調用Deferred對象注冊的‘done’回調函數并傳遞參數和設置回調上下文
deferred.isResolved 確定一個Deferred對象是否已經解決。
deferred.reject(arg1,arg2,…) 調用Deferred對象注冊的‘fail’回調函數并傳遞參數
deferred.rejectWith(context,args) 調用Deferred對象注冊的‘fail’回調函數并傳遞參數和設置回調上下文
deferred.promise() 返回promise對象,這是一個偽造的deferred對象:它基于deferred并且不能改變狀態所以可以被安全的傳遞

具體查看API http://www.css88.com/jqapi-1.9/category/deferred-object/;

jQuery延時實現的核心是jQuery.Deferred:一個可以鏈式調用的構造函數。…… 需要注意的是任何deferred對象的默認狀態是unresolved, 回調會通過 .then() 、?.fail()等方法添加到隊列,并在稍后的過程中被執行。

下面這張表格列舉了,哪些事件會觸發哪些回調:

Callbacks\ Events→
deferred.always() deferred.done() deferred.fail() deferred.progress()
deferred.notify() 觸發
deferred.notifyWith() 觸發
deferred.reject() 觸發 觸發
deferred.rejectWith() 觸發 觸發
deferred.resolve() 觸發 觸發
deferred.resolveWith() 觸發 觸發

 

靈活的?jQuery.Deferred對象

$.deferred()方法

作用是生成一個deferred對象。

var deferred = $.deferred();

done() 和 fail()

這兩個方法都用來綁定回調函數。done()指定非同步操作成功后的回調函數,fail()指定失敗后的回調函數。

var deferred = $.Deferred();
deferred.done(function(value) {
   alert(value);
});

它們返回的是原有的deferred對象,因此可以采用鏈式寫法,在后面再鏈接別的方法(包括done和fail在內)。

resolve() 和 reject()

這兩個方法用來改變deferred對象的狀態。resolve()將狀態改為非同步操作成功,reject()改為操作失敗。

var deferred = $.Deferred();
deferred.done(function(value) {
   alert(value);
});
deferred.resolve("hello world");

一旦調用resolve(),就會依次執行done()和then()方法指定的回調函數;一旦調用reject(),就會依次執行fail()和then()方法指定的回調函數。

state方法

該方法用來返回deferred對象目前的狀態。

var deferred = new $.Deferred();
deferred.state();  // "pending"
deferred.resolve();
deferred.state();  // "resolved"

該方法的返回值有三個:

  • pending:表示操作還沒有完成。
  • resolved:表示操作成功。
  • rejected:表示操作失敗。

notify() 和 progress()

progress()用來指定一個回調函數,當調用notify()方法時,該回調函數將執行。它的用意是提供一個接口,使得在非同步操作執行過程中,可以執行某些操作,比如定期返回進度條的進度。

var userProgress = $.Deferred();
    var $profileFields = $("input");
    var totalFields = $profileFields.length
    userProgress.progress(function (filledFields) {
        var pctComplete = (filledFields/totalFields)*100;
        $("#progress").html(pctComplete.toFixed(0));
    }); 
    userProgress.done(function () {
        $("#thanks").html("Thanks for completing your profile!").show();
    });
    $("input").on("change", function () {
        var filledFields = $profileFields.filter("[value!='']").length;
        userProgress.notify(filledFields);
        if (filledFields == totalFields) {
            userProgress.resolve();
        }
    });

then()

then()的作用也是指定回調函數,它可以接受三個參數,也就是三個回調函數。第一個參數是resolve時調用的回調函數,第二個參數是reject時調用的回調函數,第三個參數是progress()方法調用的回調函數。

deferred.then( doneFilter [, failFilter ] [, progressFilter ] )
在jQuery 1.8之前,then()只是.done().fail()寫法的語法糖,兩種寫法是等價的。在jQuery 1.8之后,then()返回一個新的deferred對象,而done()返回的是原有的deferred對象。如果then()指定的回調函數有返回值,該返回值會作為參數,傳入后面的回調函數。

var defer = jQuery.Deferred();
defer.done(function(a,b){
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
}).then(function( a, b ) {
            return a * b;
}).done(function( result ) {
            console.log("result = " + result);
});
defer.resolve( 2, 3 );

在jQuery 1.8版本之前,上面代碼的結果是:

result = 2 
result = 2 
result = 2

在jQuery 1.8版本之后,返回結果是

result = 2 
result = 6 
result = NaN

這一點需要特別引起注意。

$.ajax( url1, { dataType: "json" } )
.then(function( data ) {
    return $.ajax( url2, { data: { user: data.userId } } );
}).done(function( data ) {
  // 從url2獲取的數據
});

上面代碼最后那個done方法,處理的是從url2獲取的數據,而不是從url1獲取的數據。

利用then()會修改返回值這個特性,我們可以在調用其他回調函數之前,對前一步操作返回的值進行處理。

var post = $.post("/echo/json/")
    .then(function(p){
        return p.firstName;
    });
post.done(function(r){ console.log(r); });

上面代碼先使用then()方法,從返回的數據中取出所需要的字段(firstName),所以后面的操作就可以只處理這個字段了。

有時,Ajax操作返回json字符串里面有一個error屬性,表示發生錯誤。這個時候,傳統的方法只能是通過done()來判斷是否發生錯誤。通過then()方法,可以讓deferred對象調用fail()方法。

var myDeferred = $.post('/echo/json/', {json:JSON.stringify({'error':true})})
    .then(function (response) {
            if (response.error) {
                return $.Deferred().reject(response);
            }
            return response;
        },function () {
            return $.Deferred().reject({error:true});
        }
    );
myDeferred.done(function (response) {
        $("#status").html("Success!");
    }).fail(function (response) {
        $("#status").html("An error occurred");
    });

always()

always()也是指定回調函數,不管是resolve或reject都要調用。

pipe方法

pipe方法接受一個函數作為參數,表示在調用then方法、done方法、fail方法、always方法指定的回調函數之前,先運行pipe方法指定的回調函數。它通常用來對服務器返回的數據做初步處理。

promise對象

大多數情況下,我們不想讓用戶從外部更改deferred對象的狀態。這時,你可以在deferred對象的基礎上,返回一個針對它的promise對象。我們可以把后者理解成,promise是deferred的只讀版,或者更通俗地理解成promise是一個對將要完成的任務的承諾。

你可以通過promise對象,為原始的deferred對象添加回調函數,查詢它的狀態,但是無法改變它的狀態,也就是說promise對象不允許你調用resolve和reject方法。

function getPromise(){
    return $.Deferred().promise();
}
try{
    getPromise().resolve("a");
} catch(err) {
    console.log(err);
}

上面的代碼會出錯,顯示TypeError {} 。

jQuery的ajax() 方法返回的就是一個promise對象。此外,Animation類操作也可以使用promise對象。

var promise = $('div.alert').fadeIn().promise();

$.when()方法

$.when()接受多個deferred對象作為參數,當它們全部運行成功后,才調用resolved狀態的回調函數,但只要其中有一個失敗,就調用rejected狀態的回調函數。它相當于將多個非同步操作,合并成一個。

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(successFunc, failureFunc);

上面代碼表示,要等到三個ajax操作都結束以后,才執行then方法指定的回調函數。

when方法里面要執行多少個操作,回調函數就有多少個參數,對應前面每一個操作的返回結果。

$.when(
    $.ajax( "/main.php" ),
    $.ajax( "/modules.php" ),
    $.ajax( "/lists.php" )
).then(function (resp1, resp2, resp3){
    console.log(resp1);
    console.log(resp2);
    console.log(resp3);
});

上面代碼的回調函數有三個參數,resp1、resp2和resp3,依次對應前面三個ajax操作的返回結果。

when方法的另一個作用是,如果它的參數返回的不是一個Deferred或Promise對象,那么when方法的回調函數將 立即運行。

$.when({testing: 123}).done(function (x){
  console.log(x.testing); // "123"
});

上面代碼中指定的回調函數,將在when方法后面立即運行。

利用這個特點,我們可以寫一個具有緩存效果的異步操作函數。也就是說,第一次調用這個函數的時候,將執行異步操作,后面再調用這個函數,將會返回緩存的結果。

function maybeAsync( num ) {
  var dfd = $.Deferred();
  if ( num === 1 ) {
    setTimeout(function() {
      dfd.resolve( num );
    }, 100);
    return dfd.promise();
  }
  return num;
}
$.when(maybeAsync(1)).then(function (resp){
  $('#target').append('<p>' + resp + '</p>');
});
$.when(maybeAsync(0)).then(function (resp){
  $('#target').append( '<p>' + resp + '</p>');
});

上面代碼表示,如果maybeAsync函數的參數為1,則執行異步操作,否則立即返回緩存的結果。

實例

wait方法

我們可以用deferred對象寫一個wait方法,表示等待多少毫秒后再執行。

$.wait = function(time) {
  return $.Deferred(function(dfd) {
    setTimeout(dfd.resolve, time);
  });
}

使用方法如下:

$.wait(5000).then(function() {
  alert("Hello from the future!");
});

改寫setTimeout方法

在上面的wait方法的基礎上,還可以改寫setTimeout方法,讓其返回一個deferred對象。

function doSomethingLater(fn, time) {
  var dfd = $.Deferred();
  setTimeout(function() {
    dfd.resolve(fn());
  }, time || 0);
  return dfd.promise();
}
var promise = doSomethingLater(function (){
  console.log( '已經延遲執行' );
}, 100);

自定義操作使用deferred接口

我們可以利用deferred接口,使得任意操作都可以用done()和fail()指定回調函數。

Twitter = {
  search:function(query) {
    var dfr = $.Deferred();
    $.ajax({
     url:"http://search.twitter.com/search.json",
     data:{q:query},
     dataType:'jsonp',
     success:dfr.resolve
    });
    return dfr.promise();
  }
}

使用方法如下:

Twitter.search('intridea').then(function(data) {
  alert(data.results[0].text);
});

deferred對象的另一個優勢是可以附加多個回調函數。

function doSomething(arg) {
  var dfr = $.Deferred();
  setTimeout(function() {
    dfr.reject("Sorry, something went wrong.");
  });
  return dfr;
}
doSomething("uh oh").done(function() {
  alert("Won't happen, we're erroring here!");
}).fail(function(message) {
  alert(message)
});

本文被轉載1次

首發媒體 Web前端開發 | 轉發媒體

隨意打賞

提交建議
微信掃一掃,分享給好友吧。
主站蜘蛛池模板: 砍排机-锯骨机-冻肉切丁机-熟肉切片机-预制菜生产线一站式服务厂商 - 广州市祥九瑞盈机械设备有限公司 | 卡诺亚轻高定官网_卧室系统_整家定制_定制家居_高端定制_全屋定制加盟_定制家具加盟_定制衣柜加盟 | 南京租车,南京汽车租赁,南京包车,南京会议租车-南京七熹租车 | 碳纤维布-植筋胶-灌缝胶-固特嘉加固材料公司 | 变位机,焊接变位机,焊接变位器,小型变位机,小型焊接变位机-济南上弘机电设备有限公司 | 无锡网站建设_企业网站定制-网站制作公司-阿凡达网络 | 爱佩恒温恒湿测试箱|高低温实验箱|高低温冲击试验箱|冷热冲击试验箱-您身边的模拟环境试验设备技术专家-合作热线:400-6727-800-广东爱佩试验设备有限公司 | 河南不锈钢水箱_地埋水箱_镀锌板水箱_消防水箱厂家-河南联固供水设备有限公司 | 工业机械三维动画制作 环保设备原理三维演示动画 自动化装配产线三维动画制作公司-南京燃动数字 聚合氯化铝_喷雾聚氯化铝_聚合氯化铝铁厂家_郑州亿升化工有限公司 | 广州展览制作|展台制作工厂|展览设计制作|展览展示制作|搭建制作公司 | CTP磁天平|小电容测量仪|阴阳极极化_双液系沸点测定仪|dsj电渗实验装置-南京桑力电子设备厂 | 冰晶石|碱性嫩黄闪蒸干燥机-有机垃圾烘干设备-草酸钙盘式干燥机-常州市宝康干燥 | 深圳公司注册-工商注册公司-千百顺代理记账公司| 岩棉切条机厂家_玻璃棉裁条机_水泥基保温板设备-廊坊鹏恒机械 | 南京兰江泵业有限公司-水解酸化池潜水搅拌机-絮凝反应池搅拌机-好氧区潜水推进器 | 平面钻,法兰钻,三维钻-山东兴田阳光智能装备股份有限公司 | 自动焊锡机_点胶机_螺丝机-锐驰机器人 | 耐火浇注料价格-高强高铝-刚玉碳化硅耐磨浇注料厂家【直销】 | 车间除尘设备,VOCs废气处理,工业涂装流水线,伸缩式喷漆房,自动喷砂房,沸石转轮浓缩吸附,机器人喷粉线-山东创杰智慧 | 骨密度检测仪_骨密度分析仪_骨密度仪_动脉硬化检测仪专业生产厂家【品源医疗】 | 鲁尔圆锥接头多功能测试仪-留置针测试仪-上海威夏环保科技有限公司 | 牛皮纸|牛卡纸|进口牛皮纸|食品级牛皮纸|牛皮纸厂家-伽立实业 | 新能源汽车电池软连接,铜铝复合膜柔性连接,电力母排-容发智能科技(无锡)有限公司 | 合肥花魁情感婚姻咨询中心_挽回爱情_修复婚姻_恋爱指南 | 钢格板|热镀锌钢格板|钢格栅板|钢格栅|格栅板-安平县昊泽丝网制品有限公司 | 拉力测试机|材料拉伸试验机|电子拉力机价格|万能试验机厂家|苏州皖仪实验仪器有限公司 | 北京网站建设首页,做网站选【优站网】,专注北京网站建设,北京网站推广,天津网站建设,天津网站推广,小程序,手机APP的开发。 | 酒糟烘干机-豆渣烘干机-薯渣烘干机-糟渣烘干设备厂家-焦作市真节能环保设备科技有限公司 | 不锈钢反应釜,不锈钢反应釜厂家-价格-威海鑫泰化工机械有限公司 不干胶标签-不干胶贴纸-不干胶标签定制-不干胶标签印刷厂-弗雷曼纸业(苏州)有限公司 | 河南空气能热水器-洛阳空气能采暖-洛阳太阳能热水工程-洛阳润达高科空气能商行 | 济南品牌包装设计公司_济南VI标志设计公司_山东锐尚文化传播 | 高温热泵烘干机,高温烘干热泵,热水设备机组_正旭热泵 | 交通气象站_能见度检测仪_路面状况监测站- 天合环境科技 | 许昌奥仕达自动化设备有限公司| 仓储笼_仓储货架_南京货架_仓储货架厂家_南京货架价格低-南京一品仓储设备制造公司 | 混合气体腐蚀试验箱_盐雾/硫化氢/气体腐蚀试验箱厂家-北京中科博达 | 首页 - 张店继勇软件开发工作室 兰州UPS电源,兰州山特UPS-兰州万胜商贸 | 二手注塑机回收_旧注塑机回收_二手注塑机买卖 - 大鑫二手注塑机 二手光谱仪维修-德国OBLF光谱仪|进口斯派克光谱仪-热电ARL光谱仪-意大利GNR光谱仪-永晖检测 | 齿轮减速机电机一体机_齿轮减速箱加电机一体化-德国BOSERL蜗轮蜗杆减速机电机生产厂家 | 领袖户外_深度旅游、摄影旅游、小团慢旅行、驴友网 | 无锡网站建设_企业网站定制-网站制作公司-阿凡达网络 |