<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>promise学习</title>
<!-- 在js中,所有代码都是单线程执行的 -->
<!-- 异步执行:可以使用回调,在ES6中我们可以使用Promise对象来实现 -->
<!--
1.1Promise对象,只需要then一个方法,then方法带有如下三个参数
1.成功回调
2.失败回调
3.前进回调(暂时不讲)
一个全新的 promise 对象从每个 then 的调用中返回。
1.2 Promise对象代表一个异步操作,其不受外界影响,有三种状态
.Pending进行中
.Resolved(已完成,又称Fulfilled)
.Rejected(已失败)
1.3使用Promise的优势
1.3.1 解决回调地狱问题(Callback Hell)
例如,有时候我们可能会进行多个异步操作,后一个的请求需要上一次请求的返回结果,所以过去我们都是用callback层层嵌套,
但是多了的话就会出现回调地狱,代码的可读性和维护性都会变得很差
firstAsync(function(data){
//处理得到的 data 数据
//....
secondAsync(function(data2){
//处理得到的 data2 数据
//....
thirdAsync(function(data3){
//处理得到的 data3 数据
//....
});
});
});
1.3.2 使用promise的话,代码会变得扁平和可读.前面提到了then返回一个promise,因此我们可以将then的调用不停的串联起来,其中then返回的
promise装载了由调用返回的值.
firstAsync()
.then(function(data){
//处理得到的 data 数据
//....
return secondAsync();
})
.then(function(data2){
//处理得到的 data2 数据
//....
return thirdAsync();
})
.then(function(data3){
//处理得到的 data3 数据
//....
});
1.3.3 更好的进行错误捕获
多层嵌套会造成无法捕获异常,使用promise,通过使用reject方法把promise的状态设置为rejected,这样我们在then中就能捕捉到,然后执行失败情况的回调
function fetch(callback) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求失败');
}, 2000)
})
}
fetch()
.then(
function(data){
console.log('请求处理');
console.log(data);
},
function(reason, data){
console.log('触发异常');
console.log(reason);
}
);
当然我们在catch方法中处理reject回调也是可以的,
function fetch(callback) {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求失败');
}, 2000)
})
}
fetch()
.then(
function(data){
console.log('请求处理');
console.log(data);
}
)
.catch(function(reason){
console.log('触发异常');
console.log(reason);
});
-->
</head>
<body>
<script type="text/javascript">
new Promise(function(resolve, reject) {
console.log('start new Promise...');
var timeOut = Math.random() * 2;
console.log('set timeout to: ' + timeOut + ' seconds.');
setTimeout(function() {
if (timeOut < 10) {
console.log('call resolve()...');
resolve('200 OK');
} else {
console.log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}
}, timeOut * 1000);
}).then(function(r) {
console.log('Done: ' + r);
}).catch(function(reason) {
console.log('Failed: ' + reason);
});
// promise的使用详解,简单来讲,then方法就是把原来的回调写法分离出来,在异步执行操作执行完成后,用链式调用的方式,回调函数;
// 我们可以在then方法中继续写promise对象并返回,然后继续调用then进行回调操作
// then方法举例 例如 学习 考试 放假
function study() {
var p = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve("学习结束,开始考试")
}, 2000)
});
return p;
}
function test(data) {
var p = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve("考试结束,开始假期")
}, 2000)
});
return p;
}
function holiday(data) {
var p = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve("假期结束,开始上课")
}, 2000)
});
return p;
}
// 使用then链式调用这三个方法
study()
.then(function(data) {
console.log(data)
return test(data);
})
.then(function(data) {
console.log(data)
return holiday(data)
})
.then(function(data) {
console.log(data)
})
// 运行结果
// 学习结束,开始考试
// 试结束,开始假期
// 假期结束,开始上课
// 2.reject方法
function learn() {
var p = new Promise(function(reslove, reject) {
setTimeout(() => {
reject("考试不及格")
}, 1000)
});
return p;
}
learn()
.then(test, function(data) {
console.log(data + "无法放假,复习吧");
})
// 执行结果
// 考试不及格无法放假,复习吧
// 另外如果我们只要处理失败的情况,可以使用then(null,.....),或者使用catch方法
learn()
.then(null, function(data) {
console.log(data + "无法放假,复习吧");
})
// catch方法和then方法的第二个参数一样,用来指定reject的回调
learn()
.then(test)
.catch(function(data) {
console.log("没得玩了");
})
// 另一个作用是,当执行resolve的回调时,如果抛出了异常(代码出错),那么也不会报错卡死js,而是会进到这个catch中
study()
.then(function(data) {
throw new Error("考题泄漏");
test(data)
})
.catch(function(data) {
console.log(data + "无法继续考试")
})
// all方法,提供了并行异步执行操作的能力,并且在所有异步操作执行完后才会执行回调
// 例如放假要等到学习和考试之后
setTimeout(() => {
Promise.all([study(), test(),holiday()])
.then(function(data) {
console.log("开始放假了:后面的是data数据 "+data.length+"第一个:"+data[0]+"第二个:"+data[1]+"第三个:"+data[2])
// 打印结果: 开始放假了:后面的是data数据 3第一个:学习结束,开始考试第二个:考试结束,开始假期第三个:假期结束,开始上课
})
}, 1000)
// race方法,用法与all一样,只是all是等所有的异步操作完成之后,才会执行then回调.而race回调的话只要有一个异步操作执行完毕,就立刻执行then回调;
//then方法里面的回调中的参数data是一个数组,我们可以得到异步执行操作的结果
// PS:其他没有执行完毕的异步操作,仍然会继续执行,而不是停止
setTimeout(() => {
Promise.race([study(), test()])
.then(function(data) {
console.log("考试不考试,学习不学习,都没关系的")
})
}, 20000)
// race的使用场景很多,例如我们可以给某一个race设置请求超时时间
//考研开始,5s内交卷认为合格,否则认为不合格
function passTheExam() {
var p = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve("交卷")
}, 25000);
})
return p;
}
function requestTimeOut() {
var p = new Promise(function(resolve, reject) {
setTimeout(() => {
reject("考试失败")
}, 30000);
})
return p;
}
Promise.race([passTheExam(),requestTimeOut()])
.then(function(data){
console.log(data);
})
.catch(function(err){
console.log(err);
})
</script>
</body>
</html>