一、涉及技术
jquery、vue、php
二、Promise简介
MDN官方文档:Promise
三种状态:
- Pending(进行中)
- Resolved(已完成,又称 Fulfilled)
- Rejected(已失败)
只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
三、常用方法
- Promise.resolve()
- Promise.reject()
- Promise.prototype.catch()
- Promise.prototype.then()
- Promise.all()
- Promise.race()
四、简单示例
1、多个Promise使用
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('hello');
}, 1000);
});
promise.then(function(str) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(str+' world');
}, 1000);
});
}).then(function(str) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(str+' !');
}, 1000);
});
}).then(function(str) {
console.log(str); // 3秒后打印 hello world !
});
2、catch与finaly
var promise = new Promise(function(resolve, reject) {
setTimeout(function() {
reject('异步报错~');
}, 1000);
}).catch(function(err) { // 捕获reject暴露的错误
console.log(err);
}).finally(function() { // 不管resolve/reject都执行
console.log('complete');
});
五、前后端配合
1、单个Promise
后端数据
demo.php
// 获取随机字符串
function getRandChar($length) {
$str = '';
$strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz";
$max = strlen($strPol)-1;
for($i=0;$i<$length;$i++){
$str.=$strPol[rand(0,$max)];
}
return $str;
}
if($_GET['action'] == 'test') {
$data = [
["name"=>getRandChar(6), "age"=>rand(1,50)],
["name"=>getRandChar(6), "age"=>rand(1,50)],
["name"=>getRandChar(6), "age"=>rand(1,50)],
["name"=>getRandChar(6), "age"=>rand(1,50)],
];
echo json_encode($data);
}
前端页面
demo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>promise</title>
<script src="jquery.min.js"></script>
<script src="vue.min.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item, index) in list">{{ index }} {{ item.name }}</li>
</ul>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
list: []
},
mounted: function() {
var promise1 = new Promise(function(resolve, reject) {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res);
},
error: function() {
reject('请求报错~');
}
});
});
// then(fn1, fn2)里有两个回调函数,一个是resove,一个是reject
promise1.then(function(data) {
app.list = data;
}, function(err) {
console.log(err);
});
}
});
</script>
</body>
</html>
运行结果:
2、Promise.all()
Promise.all(p1, p2, ...),此方法需要所有的promise都成功才成功。。
var promise1 = new Promise(function(resolve, reject) {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res);
},
error: function() {
reject('请求报错~');
}
});
});
var promise2 = new Promise(function(resolve, reject) {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res);
},
error: function() {
reject('请求报错~');
}
});
});
var promiseAll = Promise.all([promise1, promise2]);
promiseAll.then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
结果
如果我们把其中一个url 改成 demo2.php?action=test 就会请求失败~
Promise.all() 和 jquery的$.when() 有些类似
$.when()的写法
var ajax1 = $.ajax({type: 'get', url: 'demo1.php', data: {}, dataType: 'json'}),
ajax2 = $.ajax({type: 'get', url: 'demo2.php', data: {}, dataType: 'json'}),
ajax3 = $.ajax({type: 'get', url: 'demo3.php', data: {}, dataType: 'json'});
$.when([ajax1, ajax2, ajax3]).then(function(data1, data2, data3) {
console.log(data1, data2, data3);
}, function() {
console.log('%c 请求报错~', 'color: red');
});
3、Promise.race()
Promise.race(p1, p2, ...),这个方法会返回率先成功的那个,如果都不成功,则执行reject。
var promise1 = new Promise(function(resolve, reject) {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res);
},
error: function() {
reject('请求报错~');
}
});
});
var promise2 = new Promise(function(resolve, reject) {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res);
},
error: function() {
reject('请求报错~');
}
});
});
var promiseRase = Promise.race([promise1, promise2]);
promiseRase.then(function(data) {
console.log(data);
}, function(err) {
console.log(err);
});
4、多个ajax请求
var app = new Vue({
el: '#app',
data: {
list: []
},
methods: {
ajaxReq: function(resolve, reject) {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res);
},
error: function() {
reject('请求报错~');
}
});
}
},
mounted: function() {
var promise1 = new Promise((resolve, reject) => {
this.ajaxReq(resolve, reject);
});
promise1.then((data)=> {
console.log('第一次:', data);
return new Promise((resolve, reject) => {
this.ajaxReq(resolve, reject);
});
}).then((data) => {
console.log('第二次:', data);
return new Promise((resolve, reject) => {
this.ajaxReq(resolve, reject);
});
}).then((data) => {
console.log('第三次:', data);
});
}
});
这是使用了函数封装,实际上项目中,可能不是这样的,连贯操作,可能是下一个请求需要上一个请求的返回值
var promise1 = new Promise((resolve, reject) => {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res, 2);
},
error: function() {
reject('请求报错~');
}
});
});
promise1.then((data)=> {
if(data.length > 0) {
return new Promise((resolve, reject) => {
$.ajax({
type: 'get',
url: 'demo.php?action=test',
dataType: 'json',
success: function(res) {
resolve(res.concat(data)); // 因为resolve只能接口一个参数,所以concat了一下
},
error: function() {
reject('请求报错~');
}
});
});
}
}).then((data1) => {
console.log(data1);
});