从零学前端第十六讲

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jnshu_it/article/details/84593210

本节课内容

AngularJs与服务器通信

主讲人介绍

沁修,葡萄藤技术总监

项目经验丰富,擅长H5移动项目开发。

专注技术选型、底层开发、最佳代码实践规范总结与推广。

直播录屏版

https://v.qq.com/x/page/o0760tr09zt.html

文字解析版

概述

请求与服务

在学习请求服务之前,我们首先来认识一下什么叫服务service。

在angualrjs中服务就是一个函数,它自己内建了有30多个服务。

常用的服务有哪些呢?

$location,

$http,

$timeout,

$interval…

有内建的服务那就有外部自定义的服务,因此其实我们也可以自己创建定制化的服务

app.service(’str’, function() {

    this.to = function(x) {

        return x.toString();

    }

})

创建之后,还需要在控制器里注入进去,形成依赖关系:

app.controller(‘myCtrl’, function($scope, str) {

    $scope.a = str.to({a: 1})

})

$location

$location服务分析浏览器地址栏中的URL(基于window.location),让我们可以在应用中较为方便地使用URL里面的东东。

在地址栏中更改URL,会响应到$location服务中,而在$location中修改URL,也会响应到地址栏中。

所以什么时候需要用到它呢?

在应用中,任何需要对当前URL的改变作出响应,或者想去改变当前浏览器的URL的时候。

比较一下$locationwindow.location:

目的

window.location和$location服务,都允许对当前浏览器的location进行读写访问。

API

window.location暴露一个未经加工的对象,附带一些可以直接修改的属性;

而$location服务则是暴露一些jQuery风格的getter/setter方法。

与angular应用生命周期的整合

$location知道关于所有内部生命周期的阶段,与$watch等整合;

而window.location则不行。

它不能做的事?

有,当浏览器URL改变的时候,不会导致页面重新加载(page reload)。

如果需要做这件事情(更改地址,实现page reload),请使用较低级别的API,window.location.href。

$http

$http服务就是读取远程服务器的数据的核心服务。

它是对原生XMLHttpRequest对象的简单封装,是只能接受一个参数的方法。

$http({

     url:url,           //绝对或者相对的URL路径,请求的目标

     method:method,    //表示发送的请求类型 GET/DELETE/HEAD/JSONP/POST/PUT

     params:params ,   //字符串或对象。会被转化成查询字符串加到URL后面,如果不是字符串会被JSON序列化转为?param1=xx1&m2=xx2的形式

     data: data        //字符串或者对象。包含了将被当做消息体发送给服务器的数据,通常在POST请求时使用

// 其他常用参数

// headers 对象 

在我们做POST和后台配合的时候会用到headers,其代表随请求发送的HTTP头字符串

// transformRequest 函数或函数组 

用来对HTTP请求头和体信息进行转换,并返回转化后的版本,通常用于在请求发送给服务器之前对其序列化

// transformResponse 函数或函数组 

用来HTTP响应头和响应体信息进行转换,并返回转化后的版本,通常用来反序列化

// cache 布尔值或对象。

默认情况下,$http服务不会对请求进行本地缓存,可通过向$http请求传递一个布尔参数来启用缓存。

这样在第一次请求时,http服务会向服务器发送一个请求,在第二次发送同一个请求时,会从缓存中取回请求的结果。

另外还可以为cache传入一个自定义的缓存实例来代替布尔值。

// timout 数值或者promise对象

如果为数值那么请求会在指定的毫秒后结束(会跳到失败的error方法里) ,如果为对象那么promise对象在被resolve时请求会被中止,方法执行完毕再执行请求

// responseType 字符串 

该选项会在请求中设置XMLHttpResponseType属性有以下类型: 

“”字符串默认,

”arraybuffer”(arraybuffer),

”blob”(blob对象),

“document”(HTTP文档),

”json“(从JSON对象解析出来的json字符串),

”text“(字符串),

”moz-blob“(Firefox的接收进度事件),

”moz-chunked-text“(文本流),

”moz-chunked-arraybuffer”(arraybuffer流)        

})

.then()

这个方法会返回一个promise对象,具有sccess和error两个方法。

$http({

     url:url,           //请求的url路径

     method:method,    //GET/DELETE/HEAD/JSONP/POST/PUT

     params:params ,   //转为  ?param1=xx1¶m2=xx2的形式

     data: data        //包含了将被当做消息体发送给服务器的数据,通常在POST请求时使用

}).success(response, status, header, config, statusText){

    // 响应成功时调用

}).error(res) {

    // 响应失败时调用

})

当然我们也可以在相应返回时直接使用then函数来处理回调

$http({

     url:url,           //请求的url路径

     method:method,    //GET/DELETE/HEAD/JSONP/POST/PUT

     params:params ,   //转为  ?param1=xx1¶m2=xx2的形式

     data: data        //包含了将被当做消息体发送给服务器的数据,通常在POST请求时使用

})

.then(function (res){

    // res响应对象包含5个属性,和前面说到的success是等价的。

    // 1. data(字符串或对象):响应体,就是后台返回的数据

    // 2. status:相应http的状态码,如200

    // 3. headers(函数):头信息的getter函数,可以接受一个参数,用来获取对应名字的值

    // 4. config(对象):生成原始请求的完整设置对象

    // 5. statusText:相应的http状态文本,如”ok"

})

then方法和success方法的主要区别就是,then方法会接受到完整的响应对象,而success则会对响应对象进行析构。

$http服务的快捷方法

$http提供了一些快捷方法让我们使用,一共有六个(其实是六种请求模式)

1、$http.get(url字符串,config可选的配置-对象类型) 返回HttpPromise对象

2、$http.delete(url字符串,config可选的配置-对象类型) 返回HttpPromise对象

3、$http.head(url字符串,config可选的配置-对象类型) 返回HttpPromise对象

4、$http.jsonp(url字符串,config可选的配置-对象类型) 返回HttpPromise对象

5、$http.post(url字符串,data对象或字符串,config可选的配置-对象类型) 返回HttpPromise对象

6、$http.put(url字符串,data对象或字符串,config可选的配置-对象类型) 返回HttpPromise对象

提交表单的问题

到这里大家应该都会用$http服务来与服务器通信了

但大家在开发的时候遇到post请求提交form表单数据的时候,很可能会遇到这个问题:

后端获取不到前端提交的数据。

其原因是这样的:

$http的post方法预设的content-type头是”application/json;charset=utf-8”

然后不会对数据做序列化处理,这样提交的数据格式就对不上号,让后端抓不到。

因此我们需要先对数据进行序列化处理,比如用jquery的$.param方法。

当然也可以自己尝试去写一个方法来将对象序列化

$http({

   method: "POST",

   url: "xxx",

   headers: {'Content-Type': 'application/x-www-form-urlencoded'},

   data: $.param({a:1, b:1})

}).then()

自己来序列化:

var app = angular.module(“app", function($httpProvider) {

    // Use x-www-form-urlencoded Content-Type

    $httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';

    /**

     * The workhorse; converts an object to x-www-form-urlencoded serialization.

     * @param {Object} obj

     * @return {String}

     */

    var param = function(obj) {

        var query = '', name, value, fullSubName, subName, subValue, innerObj, i;

        for(name in obj) {

            value = obj[name];

            if(value instanceof Array) {

                for(i=0; i<value.length; ++i) {

                    subValue = value[i];

                    fullSubName = name + '[' + i + ']';

                    innerObj = {};

                    innerObj[fullSubName] = subValue;

                    query += param(innerObj) + '&';

                }

            }

            else if(value instanceof Object) {

                for(subName in value) {

                    subValue = value[subName];

                    fullSubName = name + '[' + subName + ']';

                    innerObj = {};

                    innerObj[fullSubName] = subValue;

                    query += param(innerObj) + '&';

                }

            }

            else if(value !== undefined && value !== null)

                query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';

        }

        return query.length ? query.substr(0, query.length - 1) : query;

    };

    // Override $http service's default transformRequest

    $httpProvider.defaults.transformRequest = [function(data) {

        return angular.isObject(data) && String(data) !== '[object File]' ? param(data) : data;

    }];

});

Content-Type说明:

application/x-www-form-urlencoded

主要向服务器提交用户隐私相关的信息,浏览器支持

multipart/form-data

向服务器上传小文件,浏览器支持

application/json

向后台服务器提交结构化数据,RESTful 设计风格需要

text/xml

向后台服务器提交结构化数据,RESTful 设计风格需要

上传图片的问题

现在我们对于处理普通的通信应该没什么问题了,但有没有想过上传文件上传图片应该怎么办?

过去的图片上传都需要写一个表单直接刷新提交到服务器,但使用异步通信的方式呢?

实际上现在我们只需要做三件事:

1.把文件二进制化

2.使用FormData对象,将数据作为参数放到这个对象中

3.异步提交这个对象

<input onchange="upload(this.files)" type="file">

$scope.upload = function(files) {

    $scope.reader = new FileReader();   //创建一个FileReader接口

    $scope.reader.readAsDataURL(files[0]);  //FileReader的方法,把图片转成base64

    var data = new FormData();      //以下为像后台提交图片数据

    data.append('image', files[0]);

    $http({

        method: 'post',

        url: '',

        data: data,

        headers: {'Content-Type': undefined},

        transformRequest: angular.identity

    }).success(function(data) {

    })

}

contentType这里设置成了undefined

主要是因为AngularJS本身其实是默认上传的是JSON格式的(application/JSON)。

如果我们将其设置成undefined,则可以保证在data转成formData之前被识别,而之后其实Angular会帮我们自动识别的。

以上就是上节课的内容解析啦,下节预告:

微信小程序入门

讲解什么是小程序,以及开发一个小程序都需要做什么准备

随后进行一个小程序的开发实践演示

想进一步深入的同学欢迎加入我们的IT交流群565734203共同交流学习!

猜你喜欢

转载自blog.csdn.net/jnshu_it/article/details/84593210