jQuery及AngularJs的ajax请求对比

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 Wood
member[]:Lily Jones
member[]:Tom Smith
tasks[html]:2
tasks[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 Wood
member:Lily Jones
member:Tom Smith
tasks:{"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 Wood
member[]:Lily Jones
member[]:Tom Smith
tasks[html]:2
tasks[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 Wood
member[]:Lily Jones
member[]:Tom Smith
tasks[html]:2
tasks[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方法不能满足要求。上述设置是针对单个请求而言的,如果想直接改变 http http进行配置:

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'});
    }
});
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值