表单请求

也就是form表单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<form action="xxx" method="get">
<label>用户名<input type="text" name="username" placeholder="请输入用户名"/></label><br/>
<label>密码<input type="password" name="password"/></label><br/>
性别
<label><input type="radio" name="sex" value="man"/></label>
<label><input type="radio" name="sex" value="women"/></label><br/>
爱好
<label><input type="checkbox" name="zzzz" value="chang" checked="checked" id="ddd"/></label>
<label><input type="checkbox" name="zzzz" value="tiao"/></label>
<label><input type="checkbox" name="zzzz" value="rap"/>rap</label>
<label><input type="checkbox" name="zzzz" value="lanqiu"/>篮球</label><br/>
<input type="button" value="普通按钮"/><input type="submit" value="注册"/><br/>
<input type="hidden" name="hd" value="jack"/><br/>
</form>

ajax请求

ajax可以在不刷新网页的情况下,向服务器发送异步HTTP请求

xhr就是ajax的一种实现,ajax是代表的是一种开发模式,而不是具体的 API,它的核心目标是:使用 JavaScript 进行异步数据请求,从而提升网页的交互体验,ajax请求受同源策略限制

原生ajax发送GET请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("GET", "http://localhost:8080/register?username=1&password=2&time=" + new Date().getTime());
//xmlHttpRequest.setRequestHeader();
xmlHttpRequest.send();
xmlHttpRequest.onreadystatechange = function () {
// readyState 可以取值 0 1 2 3 4
//0 未初始化
//1 open方法调用完毕
//2 send方法调用完毕
//3 服务端返回部分结果
//4 服务端返回了所有结果
if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {
console.log(xmlHttpRequest.response);
console.log(xmlHttpRequest.responseText);
console.log(xmlHttpRequest.getAllResponseHeaders());
console.log(xmlHttpRequest.getResponseHeader('content-type'));
}
}

原生ajax发送POST请求

1
2
3
4
5
6
7
8
9
10
11
12
13
let xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open("POST", "http://localhost:8080/register?time=" + new Date().getTime());
xmlHttpRequest.setRequestHeader('name', 'ja');
xmlHttpRequest.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
xmlHttpRequest.send('username=1&password=2');
xmlHttpRequest.onreadystatechange = function () {
if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {
console.log(xmlHttpRequest.response);
console.log(xmlHttpRequest.responseText);
console.log(xmlHttpRequest.getAllResponseHeaders());
console.log(xmlHttpRequest.getResponseHeader('content-type'));
}
}

jquery中的ajax

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
$.get('http://localhost:8080/register?time=' + new Date().getTime(), "username=jack", function (data) {
console.log(data);
});
$.get('http://localhost:8080/register?time=' + new Date().getTime(), {username: 'jack', age: 34}, function (data) {
console.log(data);
});

$.post('http://localhost:8080/register?time=' + new Date().getTime(), "username=jack", function (data) {
console.log(data);
});
$.post('http://localhost:8080/register?time=' + new Date().getTime(), {username: 'jack', age: 34}, function (data) {
console.log(data);
});

$.ajax({
method: 'POST',
url: 'http://localhost:8080/register?time=' + new Date().getTime(),
data: {username: 'jack', age: 34},
success: function (data) {
console.log(data);
},
headers: {
name: 'jack'
}
});

$.ajax({
method: 'POST',
url: 'http://localhost:8080/register?time=' + new Date().getTime(),
data: "username=jack",
headers: {
name: 'jack'
}
}).done(function (data) {
console.log(data);
});

fech发送ajax请求

fech里的.then方法返回的也是Promise类型

1
2
3
4
5
6
7
8
9
10
11
12
fetch('http://localhost:8080/register?time=' + new Date().getTime(), {
method: 'POST',
headers: {
name: 'xiaojianbang'
},
body: 'username=xiaojianbang&password=a12345678'
}
).then(function (response) {
return response.text();
}).then(function (data){
console.log(data);
});

axios发送ajax请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
axios.get('http://localhost:8080/register?time=' + new Date().getTime(), {
params: {
username: 'xiaojianbang',
password: 'a12345678'
},
headers: {
name: 'xiaojianbang'
}
}).then(function (response) {
console.log(response.data);
});

axios.post('http://localhost:8080/register?time=' + new Date().getTime(), {
username: 'xiaojianbang',
password: 'a12345678'
}, {
params: {
getparam: 'xxxx'
},
headers: {
name: 'xiaojianbang'
}
}).then(function (response) {
console.log(response.data);
});

axios({
method: 'POST',
url: 'http://localhost:8080/register?getparam=xxx',
params: {
timestamp: new Date().getTime()
},
data: {
username: 'xiaojianbang',
password: 'a12345678'
},
headers: {
name: 'xiaojianbang'
}
}).then(function (response) {
console.log(response.data);
});

jsonp跨域请求

通过script标签直接发起请求,请求成功之后新创建标签,把获取到的数据插入到新建的script标签里,jsonp请求可以跨域

1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
function xiaojianbang(data) {
data = "前端再加工一下:" + data;
console.log("myCallback", data);
}
let scriptElement = document.createElement('script');
scriptElement.src = "http://localhost:8080/register?username=jack&password=a12345678&callback=xiaojianbang" ;
document.body.appendChild(scriptElement);

$.getJSON('http://localhost:8080/register?username=xiaojianbang&password=a12345678&callback=?', function(retval){
console.log(retval);
});
</script>

jsonp回调函数

JSONP之所以能够跨域请求并执行回调函数,关键在于 <script> 标签的特性以及浏览器对 JavaScript 代码的执行方式。

执行原理

首先前端发起 JSONP 请求

1
<script src="https://example.com/api?callback=funcname"></script>

由于 <script> 标签的 src 属性可以加载任意域的 JavaScript 代码,因此不会受到浏览器的同源策略限制。

callback=funcname 作为查询参数,告知服务器返回的 JSON 数据应如何包装。

然后服务器响应,服务器收到请求后,通常会解析 callback 参数,并返回如下格式的数据,服务器动态生成一段 JavaScript 代码,调用 funcname,并将数据作为参数传递。

1
funcname({ "message": "Hello, JSONP!" });

然后浏览器解析并执行

1
funcname({ "message": "Hello, JSONP!" });

由于 funcname 之前已经在前端定义,浏览器会调用它,并将服务器返回的数据作为参数传递。

demo

前端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>JSONP 示例</title>
</head>
<body>
<script>
function funcname(data) {
console.log("收到的数据:", data);
}
</script>
<script src="https://example.com/api?callback=funcname"></script>
</body>
</html>

服务器返回

1
funcname({"message": "Hello, JSONP!"});

由于服务器返回的数据是被前端的script标签中请求返回的,所以会被当成js代码执行

Promise

主要是解决连续异步请求,一个页面如果有很多异步请求,而且这些请求之间必须有顺序,比如先获取用户登录状态、再获取用户信息,这就会导致很多层嵌套

1
2
3
4
5
6
7
8
9
setTimeout(() => {
console.log("任务 1 完成");
setTimeout(() => {
console.log("任务 2 完成");
setTimeout(() => {
console.log("任务 3 完成");
}, 1000);
}, 1000);
}, 1000);

Promise的使用

1
2
3
4
5
6
7
8
9
10
11
12
let promise = new Promise(function (resolve, reject) {
...;
});

// .then中可以定义两个函数
// 当上面的resolve被执行的时候,第一个函数被执行
// 当reject被执行的时候,第二个函数被执行
promise.then(function (data) {
console.log('data', data);
}, function (err) {
console.log('err', err);
});

对于逆向来说,不用知道各种promise的状态,只需要知道当new Promise里面的方法被执行的时候,只能二选一执行下面的函数,至于走哪个,可以断点调试

同一个promise可以有多个then方法,而且then方法的第二个函数参数可以不传,当resolve方法被执行的时候,所有的then方法都会被执行

1
2
3
4
5
6
7
8
9
10
11
12
let promise = new Promise(function (resolve, reject) {
resolve('xiaojianbang');
});
promise.then(function (data) {
console.log('then1:', data);
});
promise.then(function (data) {
console.log('then2:', data);
});
promise.then(function (data) {
console.log('then3:', data);
});

Promise解决回调地狱

掌握几点,一是resolve函数的参数,就是下面then的第一个函数的参数,可以对数据进行处理,第二then方法的返回值也是一个Promise类型,所以可以.then连续使用,简单理解就是按顺序往下依次异步请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
function httpRequest(method, url, data, resolve, reject) {
let xmlHttpRequest = new XMLHttpRequest();
xmlHttpRequest.open(method, url);
xmlHttpRequest.setRequestHeader('name', 'xiaojianbang');
xmlHttpRequest.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
xmlHttpRequest.send(data);
xmlHttpRequest.onreadystatechange = function () {
if (xmlHttpRequest.readyState === 4 && xmlHttpRequest.status >= 200 && xmlHttpRequest.status < 300) {
resolve(xmlHttpRequest.responseText);
}
}
}

new Promise(function (resolve, reject) {
//注册
httpRequest("POST", "http://localhost:8080/register?time=" + new Date().getTime(), 'username=xiaojianbang&password=a12345678', resolve, reject);
}).then(function (data) {
console.log('注册返回的响应', data);
//判断下是注册成功的,可以进行登录
return new Promise(function (resolve, reject){
httpRequest("POST", "http://localhost:8080/register?time=" + new Date().getTime(), 'username=xiaojianbang&password=a12345678', resolve, reject);
});
}).then(function (data) {
console.log('登录返回的响应', data);
//获取登录成功的相关信息,提交获取用户信息
return new Promise(function (resolve, reject){
httpRequest("POST", "http://localhost:8080/register?time=" + new Date().getTime(), 'username=xiaojianbang&password=a12345678', resolve, reject);
});
}).then(function (data) {
console.log('获取到的用户信息', data);
//获取订单信息
return new Promise(function (resolve, reject){
httpRequest("POST", "http://localhost:8080/register?time=" + new Date().getTime(), 'username=xiaojianbang&password=a12345678', resolve, reject);
});
}).then(function (data) {
console.log('订单获取结果', data);
});