详解Angular.js的$q.defer()服务异步处理


Posted in Javascript onNovember 06, 2016

首先本文以个人目前项目的部分代码为例说明为什么要用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

 

Javascript 相关文章推荐
Zero Clipboard js+swf实现的复制功能使用方法
Mar 07 Javascript
使用jquery mobile做幻灯播放效果实现步骤
Jan 04 Javascript
javascript实现原生ajax的几种方法介绍
Sep 21 Javascript
js获取html页面节点方法(递归方式)
Dec 13 Javascript
jQuery中DOM操作实例分析
Jan 23 Javascript
jquery实现页面常用的返回顶部效果
Mar 04 Javascript
学习AngularJs:Directive指令用法(完整版)
Apr 26 Javascript
BootStrap响应式导航条实例介绍
May 06 Javascript
详解微信小程序 通过控制CSS实现view隐藏与显示
May 24 Javascript
JS中Object对象的原型概念基础
Jan 29 Javascript
ionic grid(栅格)九宫格制作详解
Jun 30 Javascript
antd Form组件方法getFieldsValue获取自定义组件的值操作
Oct 29 Javascript
Bootstrap 3.x打印预览背景色与文字显示异常的解决
Nov 06 #Javascript
d3.js实现简单的网络拓扑图实例代码
Nov 06 #Javascript
HTML5 JS压缩图片并获取图片BASE64编码上传
Nov 16 #Javascript
JS控制div跳转到指定的位置的几种解决方案总结
Nov 05 #Javascript
xcode中获取js文件的路径方法(推荐)
Nov 05 #Javascript
在js里怎么实现Xcode里的callFuncN方法(详解)
Nov 05 #Javascript
jquery.Jcrop结合JAVA后台实现图片裁剪上传实例
Nov 05 #Javascript
You might like
PHP查看SSL证书信息的方法
2016/09/22 PHP
PHP编程获取各个时间段具体时间的方法
2017/05/26 PHP
php设计模式之状态模式实例分析【星际争霸游戏案例】
2020/03/26 PHP
javascript 异常处理使用总结
2009/06/21 Javascript
用js解决数字不能换行问题
2010/08/10 Javascript
javascript学习笔记(四) Number 数字类型
2012/06/19 Javascript
关于jquery input textare 事件绑定及用法学习
2013/04/03 Javascript
js局部刷新页面时间具体实现
2013/07/04 Javascript
鼠标事件的screenY,pageY,clientY,layerY,offsetY属性详解
2015/03/12 Javascript
JavaScript在form表单中使用button按钮实现submit提交方法
2017/01/23 Javascript
nodejs中全局变量的实例解析
2017/03/07 NodeJs
jQuery+ajax实现局部刷新的两种方法
2017/06/08 jQuery
NodeJS 实现多语言的示例代码
2018/09/11 NodeJs
vue组件tabbar使用方法详解
2018/11/06 Javascript
vue根据条件不同显示不同按钮的操作
2020/08/04 Javascript
简单的Python抓taobao图片爬虫
2014/10/26 Python
python字符串对其居中显示的方法
2015/07/11 Python
python制作爬虫并将抓取结果保存到excel中
2016/04/06 Python
Python中字符串的常见操作技巧总结
2016/07/28 Python
python使用pymysql实现操作mysql
2016/09/13 Python
python中sys.argv函数精简概括
2018/07/08 Python
对pandas读取中文unicode的csv和添加行标题的方法详解
2018/12/12 Python
简单了解Python3 bytes和str类型的区别和联系
2019/12/19 Python
pyspark 随机森林的实现
2020/04/24 Python
解决Python安装cryptography报错问题
2020/09/03 Python
python实现KNN近邻算法
2020/12/30 Python
太阳镜仓库,售价20美元或更少:Sunglass Warehouse
2016/09/28 全球购物
美团网旗下网上订餐平台:美团外卖
2020/03/05 全球购物
高三自我鉴定怎么写
2013/10/19 职场文书
力学专业毕业生自荐信
2013/11/17 职场文书
办公室秘书自我鉴定
2014/01/18 职场文书
企业安全生产演讲稿
2014/05/09 职场文书
2016年劳模先进事迹材料
2016/02/25 职场文书
担保书怎么写 ?
2019/04/22 职场文书
简历自我评价范文
2019/04/24 职场文书
MySQL优化之慢日志查询
2022/06/10 MySQL