jquery和angular都有defer服务,我暂以angular为例谈谈我的理解,最后并附上jquery的阮一峰总结的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

angular中的$q.defer()服务异步处理的更多相关文章

  1. promise和Angular中的 $q, defer

    在ES6语法中,新出了promise构造函数, 可用来生成promise实例. Promise对象: 代表了未来某个将要发生的事件(通常是一个异步操作).有了promise对象, 可以将异步操作以同步 ...

  2. 形象的讲解angular中的$q与promise(转)

    以下内容摘自http://www.ngnice.com/posts/126ee9cf6ddb68 promise不是angular首创的,作为一种编程模式,它出现在……1976年,比js还要古老得多. ...

  3. 原创:形象的讲解angular中的$q与promise

    promise不是angular首创的,作为一种编程模式,它出现在……1976年,比js还要古老得多.promise全称是 Futures and promises.具体的可以参见 http://en ...

  4. angular中的$q服务实例

    用于理解$q服务 参考:http://www.zouyesheng.com/angular.html#toc39 广义回调管理 和其它框架一样, ng 提供了广义的异步回调管理的机制. $http 服 ...

  5. Angular中的$q的形象解释及深入用法

    作者:寸志链接:https://zhuanlan.zhihu.com/p/19622332来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 早上,老爸说:“儿子,天气如何 ...

  6. angularjs中使用$q.defer

    方法method1和方法method2的区别,我还正在研究中...待添加 代码如下: <html ng-app="myApp"> <head> <ti ...

  7. Angular中怎样创建service服务来实现组件之间调用公共方法

    Angular组件之间不能互相调用方法,但是可以通过创建服务来实现公共方法的调用. 实现 创建服务命令 ng g service 服务路径/服务名 比如这里在app/services目录下创建stor ...

  8. angular中的$q服务

    $q的一共有四个api: 1.$q.when(value, successFn, errorFn, progressFn),返回值为一个promise对象 --value可以是一个任意数据,也可以是一 ...

  9. 浅谈Angular的 $q, defer, promise

    浅谈Angular的 $q, defer, promise 时间 2016-01-13 00:28:00  博客园-原创精华区 原文  http://www.cnblogs.com/big-snow/ ...

随机推荐

  1. PHP之几道面试题

    1.二分查找算法 function two_find($arr,$low,$height,$k){ if($low<=$height){ $mid = intval(($low+$height) ...

  2. WCF 程序入门

    WCF是微软公司推出的符合SOA思想的分布式应用程序技术框架和编程模型,是建立在消息通信这一概念基础上运行的一个运行时服务系统. WCF编程模型的目标是实现以下两个实体之间的通信:WCF服务端和WCF ...

  3. 更加精确的定时器:dispatch_source_t

    在使用定时器时,我们经常使用NSTimer,但是由于NSTimer会受RunLoop影响,当RunLoop处理的任务很多时,就会导致NSTimer的精度降低,所以在一些对定时器精度要求很高的情况下,应 ...

  4. 利用SQl对数据库实行数据拆分与组合

    利用SQl对数据库实行数据拆分与组合实现提供以下几种方案: 方法一: WITH CTE AS (SELECT A.Id,A.[Uid],UserName FROM (SELECT A.[id], RE ...

  5. mysql解决其他服务器不可连接问题

    在安装mysql的机器上运行: 1.d:\mysql\bin\>mysql   -h   localhost   -u   root //这样应该可以进入MySQL服务器 2.mysql> ...

  6. asp.net 使用DroDownList来实现二级联动

    今天做新闻发布系统的时候,用到了二级联动,我把使用方法记录下来,以便日后查阅以及帮助新手朋友们.下面是效果图: 下面来讲解一下实现的方法: 1.在.aspx页面中,拖入两个DroDownList控件. ...

  7. 关于全排列 next_permutation() 函数的用法

    这是一个c++函数,包含在头文件<algorithm>里面,下面是基本格式. 1 int a[]; 2 do{ 3 4 }while(next_permutation(a,a+n)); 下 ...

  8. UI控件(UISegmentedControl)

    @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSArray* segmentArray = [[ ...

  9. 完全使用一组 DSL 来操作 Grid 控件

    最近尝试了一下将 XtraGrid 的初始化工作封装成内部 DSL,例如一个普通的基础数据的增删改查操作的代码会像下面这样: public partial class UserForm : XtraF ...

  10. dubbo 配置文件详解

    一.dubbo常用配置 <dubbo:service/> 服务配置,用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心. eg.<dub ...