jQuery及AngularJs的ajax请求对比

来源:互联网 发布:nasa数据查询 编辑:程序博客网 时间:2024/06/15 01:01

jQuery的$.ajax方法和AngularJs的$http服务处理方式默认是不一样的,所以对于相同的请求,后端的得到的数据格式不一样,下面总结这两种方法请求的差异以及如何自定义请求格式。
为了前后端交互,更好的查看http协议和数据,后端用Node.js和express,并用中间件处理发送的数据
定义发送的数据为:

var data = {    department: '前端',    member: ['John Wood', 'Lily Jones', 'Tom Smith'],    tasks: {        html: 2,        js: 3    }};

jQuery的GET请求

js代码为

$.ajax({    type: 'GET',    url: '/ajax/data',    data: data,    success: function(data) {        console.log(data.result);    }});

控制台查看请求为
jQuery/GET
查询字符串为:

解析前:department=%E5%89%8D%E7%AB%AF&member%5B%5D=John+Wood&member%5B%5D=Lily+Jones&member%5B%5D=Tom+Smith&tasks%5Bhtml%5D=2&tasks%5Bjs%5D=3浏览器解析后:department:前端member[]:John Woodmember[]:Lily Jonesmember[]:Tom Smithtasks[html]:2tasks[js]:3

可看到空格用+号代替,而数组和对象都解析为键值对的形式,所以后端需根据正确的方式去解析才能得到正确的数据格式,通过express的qs模块解析出来结果为:
结果
格式基本正确,但数字变为了字符串,所以为了得到正确的格式需要再进行判断或自己手写解析方法。

AngularJs的GET请求

js代码为

$http({    method: 'GET',    url: '/ajax/data',    params: data,}).success(function(data) {    console.log(data.result);});

控制台查看请求为:
AngulaJs/GET
基本和jQuery一样,除了Accept略微不同。

解析前:department=%E5%89%8D%E7%AB%AF&member=John+Wood&member=Lily+Jones&member=Tom+Smith&tasks=%7B%22html%22:2,%22js%22:3%7D浏览器解析后:department:前端member:John Woodmember:Lily Jonesmember:Tom Smithtasks:{"html":2,"js":3}

可看到AngularJs在处理数组和对象时方式和jQuery不一样,数组扩展为键值对形式,但键名没有[],对象直接转换为JSON,通过express的qs模块解析出来结果为:
结果
数组能正确解析,但对象是JSON字符串,所以需要进一步解析。

jQuery的POST请求

js代码为

$.ajax({    type: 'POST',    url: '/ajax/data',    data: data,    success: function(data) {        console.log(data.result);    }});

控制台查看请求为
jQuery/POST
查询字符串为:

解析前:department=%E5%89%8D%E7%AB%AF&member%5B%5D=John+Wood&member%5B%5D=Lily+Jones&member%5B%5D=Tom+Smith&tasks%5Bhtml%5D=2&tasks%5Bjs%5D=3浏览器解析后:department:前端member[]:John Woodmember[]:Lily Jonesmember[]:Tom Smithtasks[html]:2tasks[js]:3

可以发现jQuery的默认内容类型为application/x-www-form-urlencoded,所以查询字符串都编码为键值对的形式,而urlencoded属于w3c标准和RFC不一样,所以空格编码为+而不是%20。后端通过express以及bodyParser模块的urlencoded方法解析的结果为
结果
可看出结果与实际差别较大。

AngularJs的POST请求

js代码为

$http({    method: 'POST',    url: '/ajax/data',    data: data,}).success(function(data) {    console.log(data.result);});

控制台查看请求为
AngularJs/POST

解析前:{"department":"前端","member":["John Wood","Lily Jones","Tom Smith"],"tasks":{"html":2,"js":3}}浏览器解析后:department: "前端"member: ["John Wood", "Lily Jones", "Tom Smith"]tasks: {html: 2, js: 3}

可以发现AngularJs的默认内容类型为application/json,所以请求报文的正文是以JSON的形式发送的,而后端通过express以及bodyParser模块的json方法解析的结果为:
结果
和传输的数据格式一模一样。

数据的传输需要前后端以相同的方式进行才能保证得到正确的数据,通过了解jQuery和AngularJs的编码方式就可以在后端以对应的方式解析数据,同时可以根据需要改变框架默认的编码方式,同时制定对应的Content-Type,帮助后端识别数据类型,以满足需求

jQuery发送JSON

对于GET请求,jQuery总是会把data转换键值对形式,如果data为字符串,则以字符串的形式直接附在URL后,如果是对象则进行序列化,如果为number、null或undefined则忽略,所以以GET发送对象时,可以手动调用JSON.stringify把对象的值转换为字符串,在后端再调用JSON.parse解析。
对于POST请求,指定Content-Type,并传输对应格式,可以让数据得到正确解析,如下例子:

$.ajax({    type: 'POST',    url: '/ajax/data',    data: JSON.stringify(data),    contentType: 'application/json;charset=UTF-8',    success: function(data) {        console.log(data.result);    }});

后端解析结果:
结果

AngularJs以urlencoded编码

对于GET请求,Angular处理方式与jQuery不一样,它总是先把params参数转换为对象,再进行编码,所以不能把params直接赋值为字符串,通常我们可以利用它的编码特征,把参数设为{p:{}}的形式,在后端得到p的值再解析JSON为对象,如果一定需要像jQuery的形式,AngularJs1.5提供了一个服务$httpParamSerializerJQLike,示例如下:

$http({    method: 'GET',    url: '/ajax/data',    params: data,    paramSerializer: '$httpParamSerializerJQLike',}).success(function(data) {    console.log(data.result);});

查询字符串为:

department:前端member[]:John Woodmember[]:Lily Jonesmember[]:Tom Smithtasks[html]:2tasks[js]:3

和jQuery编码的方式一样。
对于POST请求,把Content-Type指定为application/x-www-form-urlencoded; charset=UTF-8,对于简单的对象可以自己手动转换,如把data赋值为name=wind&age=20,对于复杂对象也可以调用$httpParamSerializerJQLike服务(需要先依赖注入),示例如下:

$http({    method: 'GET',    url: '/ajax/data',    //data: 'name=wind&age=20', //手动编码    data: $httpParamSerializerJQLike(data),    headers: {        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'    }}).success(function(data) {    console.log(data.result);});

编码的结果和上面相同,当然这时后端需要对应方法解析,nodejs里bodyParser模块的urlencoded方法不能满足要求。上述设置是针对单个请求而言的,如果想直接改变httphttp进行配置:

angular.module('myApp', [])    .config(function($httpProvider) {        $httpProvider.defaults.headers.            post['Content-Type'] = 'application/x-www-form-urlencoded; charset=UTF-8';    })

也可以在运行时通过$http对象的defaults属性对这些默认值进行修改:

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

发送multipart/form-data

通过multipart/form-data类型可以发送文件、图片,在表单元素中,可以设定enctype="multipart/form-data",此时表单内容类型就为multipart/form-data,也可在JS中创建手动formData对象:

var formData = new FormData();formData.append('name', 'wind');formData.append('name', 'Jack');formData.append('age', 20);

jQuery示例:

$.ajax({    type: 'POST',    url: '/ajax/data',    data: formData,    contentType: false,    processData: false,    success: function(data) {        console.log(data.result);    }});

把contentType设为false则浏览器会自动的加上正确的Content-Type类型,如果手动写上的话可能浏览器无法识别,processData设为false让jQuery不进行处理,以原始数据发送,查看请求报文如下:
request
通过nodejs的multiparty模块解析的结果为:
结果

AngularJs示例:

$http({    method: 'POST',    url: '/ajax/data',    data: formData,    headers: {        'Content-Type': undefined    }}).success(function(data) {    console.log(data.result);});

AngularJs里把Content-Type设为undefined,表示由浏览器默认处理,请求报文除了boundary值不同基本相同与jQuery相同。

文件上传

对于文件,input的dom对象有一个files的数组,因此可把input.files[0]添加到formData对象中,一个例子:

$('#file').change(function() {    var formData = new FormData();    var file = this.files[0];    formData.append('file', file);    $.ajax({        type: 'POST',        url: '/ajax/data',        data: formData,        contentType: false,        processData: false,        success: function(data) {            console.log(data);        }    });});

附:express4路由处理代码

'use strict';const express = require('express');const router = express.Router();const multiparty = require('multiparty');const util = require('util');const fs = require('fs');module.exports = router;router.get('/', (req, res) => res.render('ajax'));router.get('/data', (req, res) => {    let data = req.query;    console.log(util.inspect(data, {colors: true}));    res.send({result: 'success'});});router.post('/data', (req, res) => {    if (req.headers['content-type'].indexOf('multipart/form-data') > -1) {        let form = new multiparty.Form({            uploadDir: './tmp',        });        form.parse(req, function(err, fields, files) {            console.log(util.inspect({fields: fields, files: files}, {colors: true, depth: null}));            if (files.file) {                let uploadPath = files.file[0].path;                let desPath = `./tmp/${files.file[0].originalFilename}`;                fs.renameSync(uploadPath, desPath);            }           });        res.send({result: 'success'});    } else {        let data = req.body;        console.log(util.inspect(data, {colors: true}));        res.send({result: 'success'});    }});
0 0
原创粉丝点击