AngularJS:与后端服务器通讯

AngularJS使用XMLHttpRequest(XHR)和JSONP请求来与后端通信,它用通用的$http服务来发布XHR和JSONP请求。

$http请求

$http APIs 实例如下:

首先有一个专用的方法发出XHR GET请求,有几种同样的其他类型的XHRrequests方法如下:

  Get:$http.get(url,config)

  POST:$http.post(url,data,config)

  Put:$http.put(url,data,config)

  Delete:$http.delete(url,config)

  Head:$http.head

JSONP请求:$http.jsonp(url, config)

$http方法接受的参数依赖于使用的HTTP方法。对于可以在body中添加数据的方法(如POST和PUT),参数如下:

  url:将要调用的目标URL

  data:将要发送的数据

  config:js对象,包含其他的影响请求和响应的配置选项。

对于其他方法(GET,DELETE,HEAD,JSONP),在请求body中没有数据发送,参数变得简单,可以简化为两个参数:url和config。

从$http方法返回的对象允许我们注册success和error回调函数。

http响应处理

请求可能会成功或者失败,AngularJS提供两种方法来注册回调函数处理两种结果:success和error.。所有的方法都接受包含以下参数的回调函数:

  data:实际返回数据

  status:响应的HTTP状态

  headers:接触到HTTP响应头的函数

  config:当请求触发时提供的配置对象

success的返回码是:200-299,其他的返回码是error。如果不注册回调函数,响应将会忽略。

同源策略

1、JSONP

浏览器可以使用script标签从外部服务器拉取js。JSONP不触发XHR请求,但是产生一个<script>标签,源指向外部资源。一旦产生的script标签出现在DOM中,浏览器执行其功能,并调用服务器,服务器在我们的web应用中使用函数调用。JSONP实例如下:

调用$http.jsonp函数,AngularJS将动态创建一个新的<script>DOM元素如下:

只要这个script标签添加到DOM中,浏览器将会请求URL,响应一旦返回,将会有内容如下:

一个JSONP响应是一个正常的JS函数调用。AngularJS产生angular.callbacks._k函数,这个函数一旦调用将会触发success回调函数。提供给$http.jsonp函数调用的URL必须包含JSON_CALLBACK请求参数。AngularJS将这个字符串转为动态生成的函数名。

JSONP的限制:

  1)仅能获取HTTP请求,错误处理将成问题,因为浏览器不会在返回给js的script标签中暴露HTTP响应状态。实际上记录http状态错误并触发出错回调函数很困难。

  2)JSONP也会暴露我们的web应用产生安全问题。除了XSS攻击,最大的问题是一个服务器能在JSONP响应中产生任意抽象的js。这个js将会被加载到浏览器中并在用户的session中执行,引起不同危害,从简单的网页奔溃到窃取敏感数据,所以我们应该通过jsonp请求谨慎选择服务并且仅使用可信任的服务器。

2、使用CORS

建立于XMLHttpRequest对象之上以一种已定义并可控的方式实现跨域AJAX请求,CORS的整体思想是:浏览器和外部服务器需要协作(通过发送合适的请求和响应头)来有条件的使用跨域请求。所以,外部服务器需要配置。浏览器必须能发送合适的请求头,并对跨域请求成功的服务器响应进行解释。

CORS请求分为simple(GET POST HEAD请求) 和 non-simple(使用HTTP动词或者允许集合之外的请求头)。

对于non-simple的请求,浏览器必须在发送最初请求之前发送探测的OPTION请求,并等待服务器的批准。仔细观察HTTP就会发现OPTIONS请求。一个删除用户的例子如下:

检查HTTP通信可以看到两个请求(OPTIONS和DELETE)指向同一个URL

3、服务器端代理

JSONP不是一个理想的跨域请求技术。CORS规范使情况好转,但仍需要在服务器端进行额外的配置,并且浏览器需要支持标准。如果无法使用CORS或JSONP技术,就是永远的选择完全避免跨域请求的问题。我们可以通过配置本地服务器作为对外部服务器的代理实现这一目标。通过采用正确的服务器配置我们可以通过我们的服务器代理跨域请求,从而让浏览器的目标只有我们的服务器。这种技术适用于所有的浏览器,并且不需要提前发生OPTIONS请求。此外,它不会添加任何附加的安全风险。这种方法的缺点是,我们需要相应地配置服务器。

promises 和 $q

$q基础

举个例子:我们通过电话预订pizza并让其快递到我们的家。虽然预定pizza只需要一个很短的电话,实际交货(订单执行)需要一定的时间,是异步的。为了感受Promise API,我们使用$q来对pizza订单及其成功交付进行建模。首先,定义一个Person,可以吃掉pizza,或者当订单未送达时感到饥饿,如下所示:

可以有个eat和beHungry方法当作success和error的回调函数。

现在对pizza预定建模并完成整个过程如下:

$q.defer()返回一个deferred对象,这个对象有两个作用:

  1)包含一个promise对象(在promise属性中)。promises是对一个deferred任务执行结果(成功或失败)的占位符

  2)暴露方法来触发任务完成(resolve)或者失败(reject)

promise API有两个作用:控制未来任务执行、执行结果。

控制任务执行的entity(在我们的例子中是restaurant)暴露一个promise对象(pizzaOrderFulfillment.promise)给对任务结果感兴趣的实体。例子中,Pawel对order感兴趣,通过在promise对象上注册回调函数来表达他的兴趣。为了注册回调函数,使用了then(successCallBack,errorCallBack)方法。这个方法接受回调函数将会在任务结果中调用。为了标志任务执行结束,需要在deferred对象上调用resolve方法。传递给resolve方法的参数将会被用来作为提供给success回调函数的值。当success回调函数调用后,任务结束,promise被resolved。通常reject方法调用将会触发error回调和promise rejection。

Promises是first-class js对象

我们可以通过他们(first-class js对象)周围的参数和函数调用返回它们。这让我们易封装异步操作的服务。如下:


restaurant服务封装了异步任务,从takeOrder方法返回一个promise,返回的promise可以被restaurant顾客使用来放置promised结果,当结果可用时notified。rejecting promises和触发error回调函数例子如下:

收集回调函数

一个promise对象可以被用来注册多个callbacks,如下所示:

多个成功的callbacks被注册,当一个promise resolve后所有这些都被触发,同样,promise rejection也会触发所有注册的error callbacks。

注册callbacks和promise生命周期

一旦promise resolved或者rejected,将不会改变其状态。仅有一次机会提供promised结果,不会出现以下情况:

  resolve一个rejected promise

  用一个不同的结果resolve一个已经resolved promise

  reject一个resolved promise

  用一个不同的rejection理由reject一个rejected promise

例如如果我们的pizza已经成功送到或者可能吃掉了再告知我们订单有问题,那就没有任何意义了。

任何注册的回调函数在一个promise resolved(rejected)后将会以同样的结果resolved(或者同样的失败缘由rejected)。

异步操作链

Promise API真正有用的地方是在异步环境中模仿同步函数调用。

继续pizza例子,想象下现在我们被朋友邀请吃pizza,我们的hosts将会预定一个比萨,一旦order到来,他们将会切块吃。有一系列异步事件:首先一个pizza需要被delivered,只有这样才能准备serving。在我们开始享用之前两个promise需要resolved:restaurant承诺送货,hosts承诺会给pizza切块并served。建模如下:

以上例子中,我们可以看到promises链(then方法)。这个结构非常类似于下面的同步代码:

同时它很容易处理错误条件。让我们来看看错误传播实例:

这里从restaurant得到的rejection结果传播到对最终结果感兴趣的person上。这正是异步环境下的异常处理:抛出的异常将会冒泡给第一个catch块。

在Promise API,error回调函数作为catch块,作为标准的catch块-我们已经得到几个处理异常情况的选项。我们可以:

  1、recover(从一个catch 块中返回值)

  2、传播failure(重新抛出异常)

有Promise API,很容易在catch块中模拟recovery。例如假定如果需要的pizza不可用,我们的hosts试图预定另一个pizza

另一种情况是如果recovery不行,我们需要考虑的是重新抛出异常。在这种情况下,唯一的选项是触发另一个error,$q服务有专用的方法($q.reject):

$ q.reject方法在异步环境中等价于抛出异常。该方法返回一个被拒绝的新的promise。

$q

$q有两个额外有用的方法:$q.all和$q.when.

聚集promises

$q.all方法使开启多个异步任务成为可能,当所有任务都完成后notified。从几个异步actions有效聚集promises,返回一个组合的promise可以作为一个连接点。为了说明$q.all方法的实用性,我们考虑从多个restaurants订食品的例子。我们要等到两个订单都到货才能享用:

其中一个action失败了,promise也会被reject

封装值作为promises

有时同样的API需要与从同步和异步actions的结果中获取。在这种情况下,通常将所有结果都视为异步。$q.when方法可以使其将js对象包装成promise。

如下所示

$q的集成

$q不仅是promise的api实现,也是与AngularJS渲染机制紧密连接的。promises可以直接暴露在scope上,并且只要promise resolved就可以自动渲染,这使我们将promise当成model值。

如下,给定以下模版:

和控制器中的代码:

Hello,world将会在两秒后自动渲染,无需人工编程干预。

$http

现在,我们已经涉及到多个promises,可以去揭秘从$http 方法调用返回的响应对象。$http调用返回一个对象,这个对象上注册了success和error回调函数。实际上,返回的对象一个完全成熟的promise,这个promise有两个额外方便的方法(success和error)。作为任何一个promise,一个从$HTTP调用返回的还具有then方法,允许我们以如下形式重写callback注册代码:

由于$HTTP服务从其方法调用上返回promise,当与后端交互时可以很容易地聚集回调,链和连接请求,以及在异步环境下可以使用复杂的错误处理。

英文原文:Mastering Web Application Development with AngularJS

时间: 2024-10-29 04:33:21

AngularJS:与后端服务器通讯的相关文章

7.app和app后端的通讯

经常有开发者问:app和后端通讯是用http协议还是私有的协议?是用长连接还是短连接?通过阅读本文,帮你解除上面的疑问. (1)是用http协议还是私有的协议? 在间谍电视剧中,经常能看到间谍们的书信都是用暗号的,就算书信被敌人截取了不怕,需要耗费一定的时间,敌人才能解开书信中的秘密. 在电影<阿凡达>, 为提升故事真实性,詹姆斯卡梅隆甚至找到语言学家,专为纳美人创造了一种自己的语言.我们看这部电影的时候,根本听不懂潘多拉星球上的纳美外星人到底说什么?纳美语共有大约1000个单词,全球能够掌握

Webpack系列:在Webpack+Vue中如何将对后端的http请求转到https的后端服务器中?

在上一篇文章(Webpack系列:在Webpack+Vue开发中如何调用tomcat的后端服务器的接口?)我们介绍了如何将对于webpack-dev-server的数据请求转发到后端服务器上,这在大部分情况下就够用了. 然后现在问题又来了,在生产环境下接口一般采用https协议,如果我们要把数据请求转发到生产服务器上怎么办? 首先会想是不是把上一篇博文中提到的proxyTable改成https就可以了,如下:     proxyTable: {                '/appserve

让你的浏览器强制在后端服务器执行而不用通过前端CDN服务器

因为后端执行时间过长,前端不等待,导致提示504错误的解决办法 504 错误是因为你的CDN服务器设置的延时有限, 超时导致的504 是前端不等待中止,是前端不行,后端应该正常 502 错误是后端无应答,是后端不行,不是前端 在你的电脑C:\Windows\System32\drivers\etc\hosts 文件里面加以下代码(50.158.99.88为域名对应的IP,cnblogs.com为你的域名) 50.158.99.88 cnblogs.com 50.158.99.88 www.cnb

【转】nginx 主动式后端服务器健康检查

原文链接  http://tengine.taobao.org/document_cn/http_upstream_check_cn.html ngx_http_upstream_check_module 该模块可以为Tengine提供主动式后端服务器健康检查的功能. 该模块在Tengine-1.4.0版本以前没有默认开启,它可以在配置编译选项的时候开启:./configure --with-http_upstream_check_module Examples http { upstream

Skype for Business后端服务器部署AlwaysOn可用性组实战篇

企业内部自建的Lync Server 2013统一通信平台,在Skype for Business Server 2015发布后,通过就地升级方式已经完成升级,原来后端数据库高可用架构保持不变,仍采用镜像和见证的自动故障转移方式.当要改变后端数据库服务器高可用架构方式,采用AlwaysOn可用性组,如何顺利部署实施呢?且看下文详细的实战部署,阅读后可以顺利改造现有后端高可用架构. 前面讲到,现有SfB后端数据库采用镜像的高可用,如何顺利的从镜像方式改为AlwaysOn可用性组,本实验环境涉及到部

nginx后端服务器返回给nginx502、504、404、执行超时等错误状态的解决方法

今天公司的网站访问的时候全部变成404页面,查看网站的文件没有问题,来检查nginx的配置的时候,发现后端的一台服务器不可用,直接访问那台后台的服务器的时候,返回的是404页面,因为upstream 里面设置了ip_hash.所以导致我怎么刷新都是404页面.由此想到了nginx的一个功能,就是当后端的服务器返回给nginx502.504.404.执行超时等错误状态的时候,nginx会自动再把这个请求转发到upstream里面别的服务器上面,从而给网站用户提供更稳定的服务. 配置如下:locat

web系统后端服务器优化

1,1. 没必要去优化页面模板,这都是一些很成熟的技术,就算你好不容易提升了10%的性能,这10%在整个页面的执行过程中只占了0.5%的比例,微乎其微,等于是前面例子中的4车道变8车道的傻瓜,我们不要去充当傻瓜. 2,数据库连接:使用连接池来减少连接次数:重复的数据库查询:使用缓存来避免重复的数据库查询:慢查询:使用索引来提升查询速度,使用连接查询替换子查询等. 3,静态文件和动态页面分开处理,应用服务器的集群,数据库的集群.Web网站优化三部曲:应用程序优化.系统结构优化.网络优化. 4,前端

nginx做反向负载均衡,后端服务器获取真实客户端ip

开门见山,操作如下: 首先,在前端nginx上需要做如下配置: location / { proxy_pass http://test1; proxy_set_hearder host $host; proxy_set_header X-Real_IP $remoute_addr; proxy_set_header $proxy_add_x_forwarded_for; }; nginx会在把请求转向后台real-server前把http报头中的ip地址进行替换:这样操作完成后,real-ser

LoadRunner对移动互联网后端服务器压力测试

一.LoadRunner简介 LoadRunner,是惠普公司研发的一款预测系统行为和性能的负载测试工具.通过以模拟上千万用户实施并发负载及实时性能监测的方式来确认和查找问题,LoadRunner能够对整个企业架构进行测试. LoadRunner11是目前比较常用的版本,有免费的超级license 最高支持6.5w个并发,目前该版本对Web网站的压力测试有很好的支持,但是不支持手机app的操作脚本录制. LoadRunner12顺应移动互联网的快速发展,增加了对手机app的操作脚本录制功能,由于