这里有新鲜出炉的 AngularJS Tutorial 中文版,程序狗速度看过来!
AngularJS 诞生于 Google 是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入,等等。
相信大家都知道 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 的意思是延迟,
可以创建一个 deferred 延迟对象实例,实例旨在暴露派生的 Promise 实例,Promise 就是一种对执行结果不确定的一种预先定义,如果成功,就 xx;如果失败,就 xx,就像事先给出了一些承诺。
- $q.defer()
用法:
一个最完整的写法:
- 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 将来会被用作
函数的参数 value。
- successCallback(success){}
- 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().
在多个 promise 必须执行成功后才能执行成功回调,传递值为数组或哈希值,数组中每个值为与 Index 对应的 promise 对象。
- $q.all()
这个方法可以将每个 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 回调都打印了返回值,那么可以用
处理在其回调打印 dataArr,则包含了所有 promise 返回值!
- $q.all()
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
来源: http://www.phperz.com/article/17/0507/330627.html