网络编程 
首页 > 网络编程 > 浏览文章

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

(编辑:jimmy 日期: 2024/11/19 浏览:3 次 )

首先本文以个人目前项目的部分代码为例说明为什么要用deferred。

function getBase64(img){//传入图片路径,返回base64
   function getBase64Image(img,width,height) {
    var canvas = document.createElement("canvas");
    canvas.width = width "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 "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;
      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

 

上一篇:js无提示关闭浏览器窗口的两种方法分析
下一篇:Bootstrap 3.x打印预览背景色与文字显示异常的解决
一句话新闻
一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?
友情链接:杰晶网络 DDR爱好者之家 南强小屋 黑松山资源网 白云城资源网 网站地图 SiteMap