一.Promise
Promise是一个接口,它用来处理的对象具有这样的特点:在未来某一时刻(主要是异步调用)会从服务端返回或者被填充属性。其核心是,promise是一个带有then()函数的对象。
为了展示它的优点,下面来看一个例子,其中需要获取用户当前的配置文件:
var currentProfile = null; var username = 'something'; fetchServerConfig(function(serverConfig) { fetchUserProfiles(serverConfig.USER_PROFILES, username, function(profiles) { currentProfile = profiles.currentProfile; }); });
上面这种处理方式存在一些问题:
1.对于代码缩进来说,这种代码就是一个噩梦,尤其在你需要链式调用很多次的时候;
2.处于回调和函数之间的错误报告非常容易丢失,除非你在每一个步骤中都手动处理错误;
3.如果需要使用currentProfile对象来做一些事情,那么你需要在最内层的回调中封装真正想要实现的逻辑,要么直接封装,要么通过一个单独的函数来封装。
Promise机制可以很好地解决这些问题。在深入了解其运行机制之前,我们来看看如何使用promise实现同样的事情:
var currentProfile = fetchServerConfig().then(function(serverConfig) { return fetchUserProfiles(serverConfig.USER_PROFILES, username); }).then(function(profiles) { return profiles.currentProfile; },function(error) { //可以在这里处理错误,在fetchServerConfig或者fetchUserProfiles中处理都可以 });
使用promise机制的优点如下:
1.可以对函数进行链式调用,所以你不会陷入代码缩进噩梦中;
2.在调用链的过程中,可以保证上一个函数调用完成之后才会调用下一个函数;
3.每一个then()调用都带有两个参数(两个都是函数)。第一个是成功之后的回调,第二个是出错之后的处理器;
4.如果调用链中出现了错误,错误将会被冒泡传递到其余的错误处理函数中。所以,最终来说,所有错误都可以在任意一个回调函数中进行处理。
你可能会问,resolve(解决)方法和reject(拒绝)方法又是什么呢?在AngularJS中,延迟调用是实现promise的一种方式。调用resolve方法将会填充promise(也就是调用success处理函数),而调用reject方法将会调用promise的错误处理函数。
二.$q和Promise
Promise接口是AngularJS组织API的基础,从根本上讲,Promise接口从以下方面对异步请求做了规范:
a.异步请求返回一个promise,而不是返回具体值;
b.Promise带有一个then函数,这个函数有两个参数:第一个参数是处理"resolved"和"sucess"事件的函数;第二个参数是处理"rejected"和"failure"事件的函数。调用这两个函数时将会把结果或者拒绝的原因作为参数传递进去;
c.只要返回结果是合法的,接口就可以保证这两个函数中的一个会被调用。
大多数deferred/Q实现都会遵守以上方式,但是AngularJS的实现比较特殊,原因如下:
a.AngularJS知道$q的存在,所以$q会被整合到作用域模型中去。这样可以使解析时的传递速度更快,并且可以减少UI的闪烁和刷新;
b.AngularJS的模板也认识$q,这样一来,接口的内容就可以被当作最终结果值(而不是当作promise)来对待,然后等获取结果之后再通知promise;
c.体积更小,因为对于常用的异步任务来说,AngularJS只实现了它们所需要的最基本、最重要的功能。
我们来看一段代码:
fetchUser(function(user) { fetchUserPermissions(user, function(permissions) { fetchUserListData(user, permissions, function(list) { //对你想要显示的数据列表做一些处理 }); }); });
使用JavaScript时,人们经常会抱怨这种可怕的、金字塔的代码缩进噩梦。从本质上来说,异步返回的方式和程序的同步处理之间存在冲突,从而导致了多重嵌套的函数,这样就更难跟踪到当前的上下文了。
另外,对错误的处理也存在同样的问题。处理错误的最佳方式是什么?你会在每一个步骤中都处理错误吗?那样会把代码搞得一团糟。
为了解决这一问题,Promise方案提供了then的概念,在成功的情况下会执行一个函数,在出错的情况下执行另一个函数,两个函数都可以进行链式调用。所以,对于上面这段代码,如果使用Promise API(至少使用AngularJS的实现),可以这样展开:
var deferred = $q.defer(); var fetchUser = function() { //在进行异步调用之后,使用响应值调用deferred.resolve deferred.resolve(user); //在出错的情况下调用 deferred.reject('Reason for failure'); } //类似地,处理fetchUserPermissions和fetchUserListData deferred.promise.then(fetchUser) .then(fetchUserPermissions) .then(fetchUserListData) .then(function(list) { //处理数据列表 },function(errorReason( { //在任何一个步骤中所发生的错误,都可以在这里处理 });
整个金字塔式的代码就被很好的平坦化了,并且提供了链式的作用域,以及一个单一的出错处理点。你可以在应用中使用同样的代码来处理异步调用,只要导入AngularJS的$q服务即可。
三.拦截响应
Promise机制还可以做一些非常酷的事情:拦截响应。
我们已经学过的内容有:向服务端发送请求、处理响应、把响应很好地包装成抽象的东西及处理异步调用。但是在真实的应用中,对于每一次服务端调用,最终还必须做一些通用的操作,例如错误处理、鉴权以及其他安全方面的处理(例如剪裁数据)。
在深入理解了$q接口之后,我们就可以使用拦截响应的方式来处理以上所有任务了。响应拦截的机制允许我们在响应到达应用之前对其进行拦截,并在上面进行一些操作,例如转换数据形式、处理错误等所有你能想到的操作。
下面来看一个例子,它会拦截响应,然后做一些很小的数据转换操作。
//把拦截器注册为一个服务 myModule.factory('myInterceptor', function($q, notifyService, errorLog) { return function(promise) { return promise.then(function(response) { //什么都不做 return response; }, function(response) { //notify服务将会使用错误信息来刷新UI notifyService(response); //同时把错误信息打印到控制台,以便调试 errorLog(response); return $q.reject(response); }); } }); //确保我们所创建的拦截器是拦截器链的一部分 $httpProvider.responseInterceptors.push('myInterceptor');
资料来源:《用AngularJS开发下一代Web应用》
相关推荐
在Promise中,可以注册当Promise状态发生变化时所要执行的回调函数。 在AngularJS中,使用$q服务来创建和处理Promises。$q服务提供了一系列方法来创建promise对象、解决(resolve)或拒绝(reject)这些promise。$q...
在AngularJS中,Promise是一种处理异步操作的强大工具,它为复杂的异步代码提供了一种更易管理和可读的结构。Promise是JavaScript中处理异步操作的一种设计模式,特别是为了应对回调地狱(nested callbacks)而引入...
AngularJS的服务是可注入的单例对象,它们提供了通用功能,如$http服务用于异步数据请求,$timeout和$interval用于定时任务,$q服务处理Promise对象等。 5. **表达式** AngularJS的模板中使用双大括号`{{ }}`来...
AngularJS内建了一些服务,如$http、$q(Promise服务)和$resource(用于与RESTful API交互)。 6. **过滤器**:过滤器用于转换数据,如`currency`用于格式化货币,`date`用于格式化日期,`limitTo`用于截取字符串...
在AngularJS中,Promise是一种强大的工具,用于处理异步操作,特别是当涉及到与服务器的数据交互时。Promise的主要目的是解决回调地狱问题,通过提供一种更优雅的方式来组织和管理异步流程。 Promise有三种基本状态...
**标题** "AngularJS中、英文API参考文档" 指的是官方提供的详细开发指南,涵盖了AngularJS框架的所有核心功能和API。这些文档是开发者在使用AngularJS进行项目开发时的重要参考资料,包括指令、服务、过滤器、...
在AngularJS中,$promise属性通常与服务如$http或$resource一起使用,它们返回一个包含Promise的对象,这个Promise对象在后台请求完成时解析为响应数据。然而,当你尝试更新一个对象两次并涉及到$promise属性时,...
在AngularJS中,Promise的实现是通过`$q`服务来完成的。 首先,Promise有三个核心状态:pending(等待中),fulfilled(已成功)和rejected(已失败)。一旦Promise的状态从pending变为fulfilled或rejected,这个...
在JavaScript和AngularJS开发中,处理异步任务是一项至关重要的能力。Promise是JavaScript中处理异步编程的一个核心概念,它允许我们以更优雅的方式编写和管理异步代码。AngularJS作为基于JavaScript的前端框架,...
AngularJS中的模块(Module)是应用的基础构造块,用于组织代码和依赖关系。`angular.module()`函数用于创建和获取模块,通过`requires`参数可以声明模块间的依赖。 2. **控制器(Controller)** 控制器是模型-...
ngCordovaHTTP 用于AngularJS 模块包装器。 安装 您可以使用凉亭: bower install ... 有关 AngularJS 中 promise 的更多信息,请阅读。 有关更多信息,请查看这篇关于文章。 确保在加载 AngularJS 后加载
在AngularJS中,Promise是处理异步操作的核心概念,它为开发者提供了一种优雅的方式来管理异步流程,尤其是在处理多个并发或序列化的异步任务时。Promise对象代表着一个将来才会有的值,可能是成功的结果,也可能是...
AngularJS 的服务是可复用的代码单元,如 $http 用于与服务器进行 HTTP 通信,$scope 作为作用域,管理着模型数据,$q 用于异步操作的承诺(Promise)管理等。服务可以通过依赖注入在多个组件之间共享,提高代码的...
($Q)orlate 用于承诺关联的简单模块,即在初始请求之外解决的承诺。 这对于处理服务缓存的异步初始化以及使用带有 signalR 的消息总线或队列等非常有用。 它还为持久消息提供了一个事件聚合器(发布者/订阅者)模型...
先说说什么是Promise,什么是$q吧。Promise是一种异步处理模式,有很多的实现方式,比如著名的Kris Kwal’s Q还有JQuery的Deffered。 什么是Promise 以前了解过Ajax的都能体会到回调的痛苦,同步的代码很容易调试,...
Promise是一个构造函数,自己身上有all、reject、resolve这几个异步方式处理值的方法,原型上有then、catch等同样很眼熟的方法,下面通过实例代码给大家讲解angularjs promise 的相关知识,感兴趣的朋友一起看看吧
7. **Promise API一致性**:Promise API在1.4中与ES6的Promise保持一致,使得异步编程更加符合现代JavaScript标准。 8. **Scope的微调**:对Scope的一些细节进行了调整,比如不再默认继承$parent scope,这有助于...