詳解Angular.js的$q.defer()服務(wù)異步處理
首先本文以個(gè)人目前項(xiàng)目的部分代碼為例說(shuō)明為什么要用deferred。
function getBase64(img){//傳入圖片路徑,返回base64
function getBase64Image(img,width,height) {
var canvas = document.createElement("canvas");
canvas.width = width ? width : img.width;
canvas.height = height ? height : img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
var dataURL = canvas.toDataURL();
return dataURL;
}
var image = new Image();
image.crossOrigin = '';
image.src = img;
var base64='';
if(img){
image.onload =function (){
base64=getBase64Image(image);
console.log(base64);//位置一
}
console.log(base64);//位置二
}
}
就這段代碼,我想要在位置二處使用base64,然后結(jié)果呢?
兩處位置都打印了,位置一得到base64,ok,沒(méi)問(wèn)題。當(dāng)我在位置二想使用base64時(shí),問(wèn)題來(lái)了?onload隊(duì)列的問(wèn)題,位置二總是無(wú)法正確的獲取到想要的base64,這個(gè)時(shí)候就可以考慮異步問(wèn)題了。
我相信大家應(yīng)該和我一樣,遇到這種情況第一反應(yīng)應(yīng)該是deferred讓函數(shù)異步執(zhí)行。
那么,我講以上代碼使用deferred之后,問(wèn)題完美解決!
function getBase64(img){//傳入圖片路徑,返回base64
function getBase64Image(img,width,height) {
var canvas = document.createElement("canvas");
canvas.width = width ? width : img.width;
canvas.height = height ? height : img.height;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
var dataURL = canvas.toDataURL();
return dataURL;
}
var image = new Image();
image.crossOrigin = '';
image.src = img;
var deferred=$q.defer();
if(img){
image.onload =function (){
deferred.resolve(getBase64Image(image));
}
return deferred.promise;
}
}
getBase64('https://img.alicdn.com/bao/uploaded/TB1qimQIpXXXXXbXFXXSutbFXXX.jpg')
.then(function(base64){
var binaryblob = function (s, type) {//blob對(duì)象
var byteString = atob(s);
var array = [];
for (var i = 0; i < byteString.length; i++) {
array.push(byteString.charCodeAt(i));
}
return new Blob([new Int8Array(array)], {type: type});
};
var binaryPictureBlob = function (dataUrl, filterHead) {//上傳base64去頭
var s = filterHead ? dataUrl.replace(/^data:image\/(png|jpeg|pjpeg|bmp|gif|x-png);base64,/, "") : dataUrl;
return binaryblob(s, "image/jpeg");
};
var pic=binaryPictureBlob(base64,true);//blob對(duì)象
//然后調(diào)接口將blob對(duì)象上傳
});
問(wèn)題解決了,我又想到了分享!那么我將我的拙見(jiàn)寫(xiě)出來(lái),請(qǐng)不吝賜教!
什么是defer?
$q是Angular的一種內(nèi)置服務(wù),它可以使你異步地執(zhí)行函數(shù),并且當(dāng)函數(shù)執(zhí)行完成時(shí)或異常時(shí)它允許你使用函數(shù)的返回值或返回執(zhí)行狀態(tài)通知等。
defer的意思是延遲,$q.defer() 可以創(chuàng)建一個(gè)deferred延遲對(duì)象實(shí)例,實(shí)例旨在暴露派生的Promise 實(shí)例,Promise就是一種對(duì)執(zhí)行結(jié)果不確定的一種預(yù)先定義,如果成功,就xx;如果失敗,就xx,就像事先給出了一些承諾。
用法:
一個(gè)最完整的寫(xiě)法:
var defer1 = $q.defer();
function fun() {
var deferred = $q.defer();
$timeout(function () {
deferred.notify("notify");
if (iWantResolve) {
deferred.resolve("resolved");
} else {
deferred.reject("reject");
}
}, 500);
return deferred.promise;
}
$q.when(fun())
.then(function(success){
console.log("success");
console.log(success);
},function(err){
console.log("error");
console.log(err);
},function(notify){
console.log("notify");
console.log(notify);
})
.catch(function(reson){
console.log("catch");
console.log(reson);
})
.finally(function(final){
console.log('finally');
console.log(final);
});
1、通過(guò)$q服務(wù)注冊(cè)一個(gè)延遲對(duì)象
var deferred=$q.defer();
2、成功解決(resolve)了其派生的promise。參數(shù)value將來(lái)會(huì)被用作successCallback(success){}函數(shù)的參數(shù)value。
deferred.resolve(success)
3、未成功解決其派生的promise。參數(shù)reason被用來(lái)說(shuō)明未成功的原因。此時(shí)deferred實(shí)例的promise對(duì)象將會(huì)捕獲一個(gè)任務(wù)未成功執(zhí)行的錯(cuò)誤,promise.catch(errorCallback(reason){...}) 。
deferred.reject(reason)
4、更新promise的執(zhí)行狀態(tài)通知
deferred.notify("notify");
5、對(duì)promise進(jìn)行處理
$q.when(fun())
.then(function(success){
console.log("success");
console.log(success);
},function(err){
console.log("error");
console.log(err);
},function(notify){
console.log("notify");
console.log(notify);
})
.catch(function(reson){
console.log("catch");
console.log(reson);
})
.finally(function(final){
console.log('finally');
console.log(final);
});
這里一般簡(jiǎn)寫(xiě)為:
fun().then(successCallback, errorCallback, notifyCallback);
注:
deferred的方法中的參數(shù)都返回給了promise與callback的參數(shù)都是一一對(duì)應(yīng)的,如:
deferred.resolve(success)的success對(duì)應(yīng)successCallback(success)的success。
這里在探討下暫時(shí)很少用的$q.all().
$q.all()在多個(gè)promise必須執(zhí)行成功后才能執(zhí)行成功回調(diào),傳遞值為數(shù)組或哈希值,數(shù)組中每個(gè)值為與Index對(duì)應(yīng)的promise對(duì)象。
這個(gè)方法可以將每個(gè)promise里的某些重復(fù)代碼或者判斷,只需要在$q.all()的回調(diào)處理一次即可,簡(jiǎn)化了代碼與工作量。
寫(xiě)法為:
var iWantResolve = true;//沒(méi)有實(shí)際意思,測(cè)試運(yùn)行resolve或reject
function promise1() {
return $q(function (resolve, reject) {
$timeout(function () {
if (iWantResolve) {
resolve("promise1 resolved");
} else {
reject("promise1 reject");
}
}, 1000)
})
}
promise1()
.then(function (s1) {//success callback
console.log(s1);
})
.catch(function (err1) {//error callback
console.log(err1);
});
function promise2() {
var deferred = $q.defer();
$timeout(function () {
deferred.notify("promise2 notify");
if (iWantResolve) {
deferred.resolve("promise2 resolved");
} else {
deferred.reject("promise2 reject");
}
}, 500);
return deferred.promise;
}
promise2()
.then(function (s2) {
console.log(s2);
}, function (err2) {
console.log(err2);
});
$q.all([promise1(), promise2()])
.then(function (dataArr) {
//promise都成功執(zhí)行后的回調(diào)函數(shù)
console.log("$q.all: ", dataArr);
}, function (err) {
console.log("$q.all: ", err)
});
像這個(gè)例子,每個(gè)promise回調(diào)都打印了返回值,那么可以用$q.all()處理在其回調(diào)打印dataArr,則包含了所有promise返回值!
jquery和angular的deferred用法大致相同,但有兩處要注意的地方:
jquery:
defer=$.Deferred(); defer.promise();
angular:
var deferred=$q.defer(); deferred.promise;
總結(jié)
以上便是我對(duì)angular的$q、deferred、promise的一些淺顯的理解,希望對(duì)大家的學(xué)習(xí)或者能有所幫助,如果有疑問(wèn)大家可以留言交流。望各位大神多多評(píng)論、指教……
最后附上:
jquery中文網(wǎng)的deferred介紹:
http://www.jquery123.com/category/deferred-object/
一位大神對(duì)jquery的deferred的總結(jié)!
阮一峰:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html
- AngularJS中update兩次出現(xiàn)$promise屬性無(wú)法識(shí)別的解決方法
- AngularJS中的Promise詳細(xì)介紹及實(shí)例代碼
- AngularJS 中的Promise --- $q服務(wù)詳解
- 詳解Javacript和AngularJS中的Promises
- AngularJS中處理多個(gè)promise的方式
- 淺談Angular的$q, defer, promise
- Angular中的Promise對(duì)象($q介紹)
- 淺析Angular2子模塊以及異步加載
- AngularJS出現(xiàn)$http異步后臺(tái)無(wú)法獲取請(qǐng)求參數(shù)問(wèn)題的解決方法
- AngularJS 實(shí)現(xiàn)按需異步加載實(shí)例代碼
- angularjs 處理多個(gè)異步請(qǐng)求方法匯總
- AngularJS中的promise用法分析
相關(guān)文章
AngularJS實(shí)現(xiàn)的自定義過(guò)濾器簡(jiǎn)單示例
這篇文章主要介紹了AngularJS實(shí)現(xiàn)的自定義過(guò)濾器,結(jié)合實(shí)例形式分析了AngularJS自定義過(guò)濾器的簡(jiǎn)單定義與使用操作技巧,需要的朋友可以參考下2019-02-02
AngularJS實(shí)現(xiàn)動(dòng)態(tài)切換樣式的方法分析
簡(jiǎn)單實(shí)現(xiàn)AngularJS輪播圖效果
使用AngularJS制作一個(gè)簡(jiǎn)單的RSS閱讀器的教程
AngularJS實(shí)現(xiàn)在ng-Options加上index的解決方法

