AngularJS 用promises和$q处理异步调用
来源:互联网 发布:知乎 女生 打男朋友 编辑:程序博客网 时间:2024/06/06 02:03
AngluarJS $q 是受Chris Kowal’s Q库启发(https://github.com/kriskowal/q) 。 这个库通过一个回调“promise”让用户监控异步过程。 下面针对使用pormise的语法进行说明。
var promise = callThatRunsInBackground();promise.then( function(answer) { // do something }, function(error) { // report something }, function(progress) { // report progress });
返回promise的服务有很多,例如$http, $interval, $timeout。
所有的promise返回一个单例对象, 由我们自己决定它来返回什么。例如$http.get 它的返回对象包含四个键值:data,status, header, config. 这些参数与success回调参数一样,如:
// this$http.get('/api/v1/movies/avengers') .success(function(data, status, headers, config) { $scope.movieContent = data; });// is the same asvar promise = $http.get('/api/v1/movies/avengers');promise.then( function(payload) { $scope.movieContent = payload.data; });
在这个例子中,我们忽略error函数,以及promise的错误,update回调函数。初学者可能会疑惑,为什么我们要这么费力的获取一个答案。但每个人在开始写angluar中non-trivial服务时都会碰壁—–如何传递一个回调函数到一个调用函数,当服务返回早于回调调用前?
Promises and Services
Angular的语法要求我们用promise作为一个callback handle, 在service中进行异步操作,返回一个promise, 当异步工作完成时,然后promise的函数被调用。有了一个思路后,我们建立一个简单的controller和service例子来获取数据,并在页面中显示数据。
angular.module('atTheMoviesApp', []) .controller('GetMoviesCtrl', function($log, $scope, movieService) { $scope.getMovieListing = function(movie) { var promise = movieService.getMovie('avengers'); promise.then( function(payload) { $scope.listingData = payload.data; }, function(errorPayload) { $log.error('failure loading movie', errorPayload); }); }; }) .factory('movieService', function($http) { return { getMovie: function(id) { return $http.get('/api/v1/movies/' + id); } } });
现在你可能学会调用 异步调用$http方法,获取一个result,并更新用户界面。 服务不会理解UI的含义,你也不能将$scope传递到getMovie函数中, 这样看似很好,然而。。
那怎么进行post操作呢
下载端绑定一个$http.get promise,并将其传递给controller,controller会自己处理这个结果。 如果你想要服务 进行 post-process? 更重要的是,如果你想处理 $http 的error,在服务层,而controller不需要直接处理 404s 等
在更复杂的情况,你可能解决这个问题,通过建立自己的promise,重构service来使用promise,这样就可以在service中处理和拿回我们想要的负载。
....factory('movieService', function($http, $log, $q) { return { getMovie: function(movie) { var deferred = $q.defer(); $http.get('/api/v1/movies/' + movie) .success(function(data) { deferred.resolve({ title: data.title, cost: data.price}); }).error(function(msg, code) { deferred.reject(msg); $log.error(msg, code); }); return deferred.promise; } } });
更有前途的理由是,我们构建一个内嵌的promise结构,可以控制调用的input和output,合适的log error,转换output,并且提供一个状态来更新 deferred.notify(msg)。
But there is a better, more foolproof way…
但是有一个更好的方法,更简单
Composing Promises 组合promises
我们可以避免创建自己的deferred对象,通过结合一个then转换自己的response,返回一个转换的结果到调用着,来管理分散的promise。例如,我们想包含$http所响应的数据,而不用处理自己的deferred对象:
this.getMovie = function(movie) { return $http.get('/api/v1/movies/' + movie) .then( function (response) { return { title: response.data.title, cost: response.data.price }); });};
现在这个内容返回到服务方法的then中,将形成一个链promise,它来转换输出。而controller可以做没http的工作
$scope.getMovie = function(movie) { service.getMovie(movie) .then(function(movieData) { $scope.movieData = movieData; });};
我减少这个代码量,来实现一相同的结果,我们不需要担心在Ajax中将会发生失败的事情。
Handling problems in nested service calls
在service calls 中处理问题
现在我们用一个内嵌的返回 success 函数, promise代码将自动检测error函数的缺失,并终止调用默认的$http的error对象。 但是,你可能会担心如何转换error呢?
this.getMovie = function(movie) { return $http.get('/api/v1/movies/' + movie) .then( function (response) { return { title: response.data.title, cost: response.data.price }); }, function (httpError) { // translate the error throw httpError.status + " : " + httpError.data; });};
现在error返回一个单string,不是$http 的error, data、status、 header和config属性。
Doing more than one thing at a time 一次做更多
这是一个强大的service, 当需要同时处理多个异步活动时。 $q功能让我们同时调用多个回调函数,利用单一函数来连接他们。
service('asyncService', function($http, $q) { return { loadDataFromUrls: function(urls) { var deferred = $q.defer(); var urlCalls = []; angular.forEach(urls, function(url) { urlCalls.push($http.get(url.url)); }); // they may, in fact, all be done, but this // executes the callbacks in then, once they are // completely finished. $q.all(urlCalls) .then( function(results) { deferred.resolve( JSON.stringify(results)) }, function(errors) { deferred.reject(errors); }, function(updates) { deferred.update(updates); }); return deferred.promise; } }; });
这个例子中的负载包含一组对象,Url 如下:
[ { url: 'ajax1.html' }, { url: 'ajax2.html' }, { url: 'ajax3.html' }]
对于每个URL,一个promise 由执行$http.get创建,promise添加到一个数组中,在$q.all 的函数获取一个数组promise, 一个转换结果到一个promise 包含一个对象:
[ promise1_result_payload, promise2_result_payload, promise3_result_payload]
如果这三个调用完成,这个代码将转换为JSON到caller
from:http://chariotsolutions.com/blog/post/angularjs-corner-using-promises-q-handle-asynchronous-calls/
- AngularJS 用promises和$q处理异步调用
- “JavaScript Promises和AngularJS $q Service”Part 1 (基础篇)
- “JavaScript Promises和AngularJS $q Service”Part 2 (教程篇)
- “JavaScript Promises和AngularJS $q Service”Part 1 (基础篇)
- 理解 AngularJS $q service and promises
- angularJS系列之$q处理异步通知
- 异步js调用:callback,listeners,control flow libs 和 promises
- Using AngularJS Promises
- AngularJS中异步操作与$q.defer()
- AngularJS中异步操作与$q.defer()
- AngularJS 的 $q 和 Promise
- 异步调用,异步处理
- Node.js中,q在链式调用和异步调用中起到的作用
- Promises与Javascript异步编程
- [Sencha ExtJS] 异步 JavaScript: Promises
- angularjs系列之轻松使用$q进行异步编程
- angularJS中的promise模式以及通过$q解决异步
- angularjs结合$http、$q服务实现多个异步请求
- 安装 ODAC
- 变量
- Android自定义圆角ImageView 支持网络图片
- 30. Substring with Concatenation of All Words 算法分析及其优化
- iOS setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key 问题
- AngularJS 用promises和$q处理异步调用
- 王学岗RecylerView(一)
- mysql架构解析
- dbms_random.string用法
- 南洋理工ACM 53无聊的小明
- TopCoder SRM 637 Div2 B
- 银行自动存取一体机例题
- WebVeiw 宽度自适应
- LeetCode 316: Remove Duplicate Letters