$q
$q是Angular的一种内置服务,它可以使你异步地执行函数,并且当函数执行完成时它允许你使用函数的返回值(或异常)。
$q的其他方法
$q.when(value)
//传递变量值,promise.then()执行成功回调
//接收第一个参数为一个任意值或者是一个promise对象,
//其他3个同promise的then方法,返回值为一个promise对象。
//第一个参数若不是promise对象则直接运行success回调且消息为这个对象,
//若为promise那么返回的promise其实就是对这个promise类型的参数的一个包装而已,
//被传入的这个promise对应的defer发送的消息,
//会被我们when函数返回的promise对象所接收到。
$q.all(promises)
//多个promise必须执行成功,才能执行成功回调,
//传递值为数组或哈希值,
//数组中每个值为与Index对应的promise对象。
//参数接收为一个promise数组,
//返回一个新的单一promise对象,
//当这些promise对象对应defer对象全部解决这个单一promise对象才会解决,
//当这些promise对象中有一个被reject了,
//这个单一promise同样的被reject了。
defer
defer的字面意思是延迟,$q.defer() 可以创建一个deferred实例(延迟对象实例)。defer主要是用来发送消息的。
deferred 实例旨在暴露派生的Promise 实例,以及被用来作为成功完成或未成功完成的信号API,以及当前任务的状态。这听起来好复杂的样子,总结$q, defer, promise三者之间的关系如下所示。
var deferred = $q.defer();
//通过$q服务注册一个延迟对象 deferred
var promise = deferred.promise;
//通过deferred延迟对象,
//可以得到一个承诺promise,
//而promise会返回当前任务的完成结果
defer的方法:
deferred.resolve(value)
成功解决(resolve)了其派生的promise。
参数value将来会被用作
promise.then(
successCallback(value){...},
errorCallback(reason){...},
notifyCallback(notify){...}
)
中successCallback函数的参数。
deferred.reject(reason)
未成功解决其派生的promise。
参数reason被用来说明未成功的原因。此时deferred实例的promise对象将会捕获一个任务未成功执行的错误,
promise.catch(errorCallback(reason){...})。
补充一点,
promise.catch(errorCallback)实际上就是promise.then(null, errorCallback)的简写。
notify(value)
更新promise的执行状态.
(翻译的不好,原话是provides updates on the status of the promise’s execution)
defer的小例子:
function asyncGreet(name) {
var deferred = $q.defer(); //通过$q.defer()创建一个deferred延迟对象,
//在创建一个deferred实例时,
//也会创建出来一个派生的promise对象,
//使用deferred.promise就可以检索到派生的promise。
deferred.notify('About to greet ' + name + '.');
//延迟对象的notify方法。
if (okToGreet(name)) {
deferred.resolve('Hello, ' + name + '!');
//任务被成功执行
} else {
deferred.reject('Greeting ' + name + ' is not allowed.');
//任务未被成功执行
}
return deferred.promise;
//返回deferred实例的promise对象
}
function okToGreet(name) {
//只是mock数据,实际情况将根据相关业务实现代码
if(name == 'Superman') return true;
else return false;
}
var promise = asyncGreet('Superman');
//获得promise对象
//promise对象的then函数会获得当前任务
//也就是当前deferred延迟实例的执行状态。
//它的三个回调函数分别会在resolve(),
//reject() 和notify()时被执行
promise.then(function(greeting) {
alert('Success: ' + greeting);
}, function(reason) {
alert('Failed: ' + reason);
}, function(update) {
alert('Got notification: ' + update);
});
promise
当创建一个deferred实例时,promise实例也会被创建。通过deferred.promise就可以检索到deferred派生的promise。
promise的目的是允许interested parties 访问deferred任务完成的结果。 promise 是 Js异步编程模式的一种模式,以同步操作的流程形式来操作异步事件,避免了层层嵌套,可以链式操作异步事件。
按照CommonJS的约定,promise是一个与对象交互的接口,表示一个动作(action)的结果是异步的,而且在任何给定的时间点上可能或不可能完成。(这句话好绕口,我的理解是promise相当于一个承诺,承诺你这个任务在给定的时间点上可能会完成,也可能完成不了。如果完成了那就相当于resolve, 如果未完成就相当于reject。不知道这样理解对不对?)
每个任务都有三种状态:未完成(pending)、完成(fulfilled)、失败(rejected)。
pending状态:可以过渡到履行或拒绝状态。
fulfilled状态:不能变为其他任何状态,而且状态不能改变,必须有value值。
rejected状态:不能变为其他任何状态,而且状态不能改变,必须有reason。
状态的转移是一次性的,状态一旦变成fulfilled(已完成)或者failed(失败/拒绝),就不能再变了。
deffered 对象的方法:
resolve(value):在声明resolve()处,表明promise对象由pending状态转变为resolve。
向promise对象异步执行体发送消息告诉他我已经成功完成任务,value即为发送的消息。
reject(reason):在声明resolve()处,表明promise对象由pending状态转变为rejected。
向promise对象异步执行体发送消息告诉他我已经不可能完成这个任务了,value即为发送的消息。
notify(value) :在声明notify()处,表明promise对象unfulfilled状态,在resolve或reject之前可以被多次调用。
向promise对象异步执行体发送消息告诉他我现在任务完成的情况,value即为发送的消息。
这些消息发送完promise会调用现有的回调函数。
deffered 对象属性:
promise :最后返回的是一个新的deferred对象 promise 属性,而不是原来的deferred对象。这个新的Promise对象只能观察原来Promise对象的状态,而无法修改deferred对象的内在状态可以防止任务状态被外部修改。
promise 的方法:
then(successCallback, errorCallback, nitifyCallback)
//根据promise被resolve/reject,
//或将要被resolve/reject,调用successCallback/errorCallback。
//then方法用来监听一个Promise的不同状态。errorHandler监听failed状态,
//fulfilledHandler监听fulfilled状态,
//progressHandler监听unfulfilled(未完成)状态。
//此外,notify 回调可能被调用0到多次,提供一个进度指示在解决或拒绝(resolve和rejected)之前。
catch(errorCallback)
// then(null, errorCallback)的缩写。
finally(callback, notifyCallback)
//让你可以观察到一个 promise 是被执行还是被拒绝,
//但这样做不用修改最后的 value值。
//这可以用来做一些释放资源或者清理无用对象的工作,
//不管promise 被拒绝还是解决。
补充说明:
promise.then()会返回一个新的衍生promise,形成promise链。
例如:
promiseB = promiseA.then(function(result) {
return result + 1;
});
// promiseB will be resolved immediately
// after promiseA is resolved and its value
// will be the result of promiseA incremented by 1
// promiseB 将会在处理完 promiseA 之后立刻被处理,
// 并且其 value值是promiseA的结果增加1
$http 服务
$http 服务只是简单封装了浏览器原生的XMLHttpRequest对象,接收一个参数,这个参数是一个对象,包含了用来生成HTTP请求的配置内容,这个函数返回一个promise对象,具有success和error方法。
$http服务的使用场景:
var promise = $http({
method:"post",
// 可以是get,post,put, delete,head,jsonp;常使用的是get,post
url:"./data.json",
//请求路径
params:{'name':'lisa'},
//传递参数,字符串map或对象,转化成?name=lisa形式跟在请求路径后面
data:blob,
//通常在发送post请求时使用,发送二进制数据,用blob对象。
}).success(function(data){
//响应成功操作
}).error(function(data){
//响应失败(响应以错误状态返回)操作
})
//或
$http({
url:'data.json',
method:'GET'
}).success(function(data,header,config,status){
//响应成功
}).error(function(data,header,config,status){
//处理响应失败
});
then()函数:可以使用then()函数来处理$http服务的回调,then()函数接受两个可选的函数作为参数,表示success或error状态时的处理,也可以使用success和error回调代替:
then(successFn, errFn, notifyFn)
无论promise成功还是失败了,当结果可用之后, then都会立刻异步调用successFn或者errFn。这个方法始终用一个参数来调用回调函数:结果,或者是拒绝的理由。
在promise被执行或者拒绝之前, notifyFn回调可能会被调用0到多次,以提供过程状态的提示.
处理回调方式一:promise.then
promise.then(function(resp){
//响应成功时调用,resp是一个响应对象
}, function(resp) {
// 响应失败时调用,resp带有错误信息
});
then()函数接收的resp(响应对象)包含5个属性:
- data(字符串或对象):响应体
- status:相应http的状态码,如200
- headers(函数):头信息的getter函数,可以接受一个参数,用来获取对应名字的值
- config(对象):生成原始请求的完整设置对象
- statusText:相应的http状态文本,如”ok”
或者使用success/error方法,使用。
处理回调方式二:promise.success/error
//成功处理
promise.success(function(data, status, headers, config){
// 处理成功的响应
});
// 错误处理
promise.error(function(data, status, headers, config){
// 处理非成功的响应
});
两种方法的区别:then()方法与其他两种方法的主要区别是,它会接收到完整的响应对象,而success()和error()则会对响应对象进行析构。
使用实例:
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>$http request test </title>
<script src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/angular.min.js"></script>
<script src="http://sandbox.runjs.cn/uploads/rs/376/pbcx3e1z/angular-route.min.js"></script>
<script src="app.js"></script>
</head>
<body>
<div data-ng-app="myApp" data-ng-controller="myAppController" data-ng-init="loadData()">
<table>
<thead>
<tr>
<th>名称</th>
<th>属性</th>
</tr>
</thead>
<tbody>
<tr data-ng-repeat="data in myData">
<td>{{data.name}}</td>
<td>{{data.attr}}</td>
</tr>
</tbody>
</table>
</div>
</body>
</html>
app.js
var myHttpApp = angular.module("myApp", []);
myHttpApp.controller("myAppController", function ($q, $http, $scope) {
var deffer = $q.defer();
var data = new Blob([{
"name": "zhangsan"
}]);
$scope.loadData = function () {
var promise = $http({
method: "post",
url: "./data.json",
cache: true
}).success(function (data) {
deffer.resolve(data);
}).error(function (data) {
deffer.reject(data);
});
promise.then(function (data) {/*//响应成功时调用,data是一个响应对象*/
$scope.myData = data.data;
});
/*promise.success(function(data){
$scope.myData = data;
})*/
}
})
data.json
[
{"name":"zhangsan","attr":"China"},
{"name":"lisa","attr":"USA"},
{"name":"Bob","attr":"UK"},
{"name":"Jecy","attr":"Jepan"}
]
效果
参考: