什么是Promise?
Promise 是异步编程的一种解决方案:
- 从语法上讲:promise是一个对象,从它可以获取异步操作的消息;
- 从本意上讲:它是承诺,承诺它过一段时间会给你一个结果。
Promise 有三种状态:pending(等待)、fulfiled(满足)、rejected(失败);状态一旦改变,就不会在变,创造promise实例后,它会立即执行。
- pending: 等待状态,比如正在进行网络请求,或者定时器没有到时间
- fulfiled: 满足状态;当我们主动回调了resolve时,就处于该状态,并且会回调
.then()
- reject: 拒绝状态;当我们主动回调了reject时,就处于该状态,并且会回调
.catch()
Promise是用来解决两个问题的:
- 回调地狱,代码难以维护,常常第一个函数的输出是第二个函数的输入这种现象;
- promise可以支持多个并发的请求,获取并发请求中的数据
- 这个promise可以解决异步问题,本身不能说promise是异步的
Promise的基本使用
什么时候使用Promise?
一般情况下有异步加载的情况下进行Promise封装.
<script>
// 参数 --> 函数(resolve, reject)
// resolve,reject 本身又是函数
// 链式编程
new Promise(((resolve, reject) => {
// 假设第一次网络请求
setTimeout(() => {
resolve()
},10000)
})).then(() => {
// 第一次网络请求成功之后处理的代码
console.log("第一次网络请求成功之后处理的代码");
return new Promise(((resolve, reject) => {
// 假设第二次网络请求
setTimeout(() => {
resolve()
},10000)
}))
}).then(() => {
// 第二次网络请求成功之后处理的代码
console.log("第二次网络请求成功之后处理的代码");
return new Promise(((resolve, reject) => {
// 假设第三次网络请求
setTimeout(() => {
reject()
},10000)
}))
}).catch(() => {
// 第三次网络请求失败后处理的代码
console.log("第三次网络请求失败后处理的代码");
})
</script>
执行结果为:
当我们在执行异步操作时,使用Promise中的resolve做成功处理;reject做失败处理;
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success.Promise")
reject("error.Promise")
},2000)
}).then((data) => {
console.log(data)
}).catch((data) => {
console.log(data)
})
另一种处理方式:
new Promise((resolve, reject) => {
setTimeout(() => {
resolve("success.Promise")
reject("error.Promise")
},2000)
}).then(data => {
console.log(data)
}, err => {
console.log(err)
})
Promise 的all处理
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
<script>
// 网络请求一
// 网络请求二
Promise.all([
new Promise(((resolve, reject) => {
$.ajax({
url: "url1",
success: function(data) {
resolve(data)
},
error: function(err) {
reject(err)
}
})
})),
new Promise(((resolve, reject) => {
$.ajax({
url: "url2",
success: function(data) {
resolve(data)
},
error: function(err) {
reject(err)
}
})
}))
]).then(results => {
// 两个都成功则成功
console.log(results[0])
console.log(results[1])
} , err => {
// 有一个失败则失败
console.log(err)
})
</script>
race的用法:谁跑的快,以谁为准执行回调
race的使用场景:比如我们可以用race给某个异步请求设置超时时间,并且在超时后执行相应的操作,代码如下:
<script>
// 请求一张图片
function requestImg(){
var p = new Promise((resolve, reject) => {
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'https://img11.360buyimg.com/ling/jfs/t21382/242/710567581/125401/630d6b14/5b161ac7N5de78bc7.jpg';
});
return p;
}
//延时函数,用于给请求计时
function timeout(){
var p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('图片请求超时');
}, 5000);
});
return p;
}
Promise.race([requestImg(),timeout()]).then(data => {
console.log(data)
},err => {
console.log(err)
})
</script>
requestImg函数会异步请求一张图片,timeout函数是一个延时5秒的异步操作。我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。运行结果如下: