详解Angular.js的$q.defer()服务异步处理
首先本文以个人目前项目的部分代码为例说明为什么要用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,然后结果呢?
两处位置都打印了,位置一得到base64,ok,没问题。当我在位置二想使用base64时,问题来了?onload队列的问题,位置二总是无法正确的获取到想要的base64,这个时候就可以考虑异步问题了。
我相信大家应该和我一样,遇到这种情况第一反应应该是deferred让函数异步执行。
那么,我讲以上代码使用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 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对象 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对象 //然后调接口将blob对象上传 });
问题解决了,我又想到了分享!那么我将我的拙见写出来,请不吝赐教!
什么是defer?
$q是Angular的一种内置服务,它可以使你异步地执行函数,并且当函数执行完成时或异常时它允许你使用函数的返回值或返回执行状态通知等。
defer的意思是延迟,$q.defer()
可以创建一个deferred延迟对象实例,实例旨在暴露派生的Promise 实例,Promise就是一种对执行结果不确定的一种预先定义,如果成功,就xx;如果失败,就xx,就像事先给出了一些承诺。
用法:
一个最完整的写法:
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、通过$q服务注册一个延迟对象
var deferred=$q.defer();
2、成功解决(resolve)了其派生的promise。参数value将来会被用作successCallback(success){}
函数的参数value。
deferred.resolve(success)
3、未成功解决其派生的promise。参数reason被用来说明未成功的原因。此时deferred实例的promise对象将会捕获一个任务未成功执行的错误,promise.catch(errorCallback(reason){...})
。
deferred.reject(reason)
4、更新promise的执行状态通知
deferred.notify("notify");
5、对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); });
这里一般简写为:
fun().then(successCallback, errorCallback, notifyCallback);
注:
deferred的方法中的参数都返回给了promise与callback的参数都是一一对应的,如:
deferred.resolve(success)的success对应successCallback(success)的success。
这里在探讨下暂时很少用的$q.all().
$q.all()
在多个promise必须执行成功后才能执行成功回调,传递值为数组或哈希值,数组中每个值为与Index对应的promise对象。
这个方法可以将每个promise里的某些重复代码或者判断,只需要在$q.all()
的回调处理一次即可,简化了代码与工作量。
写法为:
var iWantResolve = true;//没有实际意思,测试运行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都成功执行后的回调函数 console.log("$q.all: ", dataArr); }, function (err) { console.log("$q.all: ", err) });
像这个例子,每个promise回调都打印了返回值,那么可以用$q.all()
处理在其回调打印dataArr,则包含了所有promise返回值!
jquery和angular的deferred用法大致相同,但有两处要注意的地方:
jquery:
defer=$.Deferred(); defer.promise();
angular:
var deferred=$q.defer(); deferred.promise;
总结
以上便是我对angular的$q、deferred、promise的一些浅显的理解,希望对大家的学习或者能有所帮助,如果有疑问大家可以留言交流。望各位大神多多评论、指教……
最后附上:
jquery中文网的deferred介绍:
http://www.jquery123.com/category/deferred-object/
一位大神对jquery的deferred的总结!
阮一峰:http://www.ruanyifeng.com/blog/2011/08/a_detailed_explanation_of_jquery_deferred_object.html
- AngularJS中update两次出现$promise属性无法识别的解决方法
- AngularJS中的Promise详细介绍及实例代码
- AngularJS 中的Promise --- $q服务详解
- 详解Javacript和AngularJS中的Promises
- AngularJS中处理多个promise的方式
- 浅谈Angular的$q, defer, promise
- Angular中的Promise对象($q介绍)
- 浅析Angular2子模块以及异步加载
- AngularJS出现$http异步后台无法获取请求参数问题的解决方法
- AngularJS 实现按需异步加载实例代码
- angularjs 处理多个异步请求方法汇总
- AngularJS中的promise用法分析
相关文章
Angular中的ng-template及angular 使用ngTemplateOutlet 指令的方法
ng-template 是用来定义模板的,当使用ng-template定义好一个模板之后,可以用ng-container和templateOutlet指令来进行使用。这篇文章给大家介绍了Angular中的ng-templateangular及使用 ngTemplateOutlet 指令的方法,需要的朋友参考下吧2018-08-08angular基于ng-alain定义自己的select组件示例
这篇文章主要介绍了angular基于ng-alain定义自己的select组件示例,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧2018-02-02详解使用angularjs的ng-options时如何设置默认值(初始值)
本篇文章主要介绍了详解使用angularjs的ng-options时如何设置默认值(初始值),具有一定的参考价值,有兴趣的可以了解一下2017-07-07
最新评论