首页 > 学院 > 开发设计 > 正文

Angular的 $q, defer, promise,$http

2019-11-08 00:31:05
字体:
来源:转载
供稿:网友

$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服务注册一个延迟对象 deferredvar 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的状态码,如200headers(函数):头信息的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"}]

效果

参考:

浅谈Angular的 $q, defer, promise

AngularJS的$http服务的应用

AngularJS中$http服务的简单用法


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表