什么是Promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作
并可以获取其成功或失败的结果;
为什么要使用Promise
Promise比较常见的使用场景就是网络请求(网络请求是异步操作),当我们发起一个请求时不能立即拿到结果,所以我们会传入另外一个函数,在数据请求成功时,将数据通过传入的函数回调出去。
如果是一个简单的网络请求不会对我们带来较大的困惑
但是在实际开发中,往往需要我们先拿到请求的数据,在去执行同步的任务,所以Promise可以使我们的异步代码看起来像同步代码一样
这里我们先来举一个栗子;现在有一个需求:小明在快餐店想要喝奶茶和吃火锅,奶茶是2秒做出了,火锅是4秒做出了,我们可以通过代码来实现
// 做奶茶的函数
function getTea(fn) {
setTimeout(() => {
fn("奶茶");
}, 2000);
}
// 做火锅的函数
function getHotpot(fn) {
setTimeout(() => {
fn("火锅");
}, 4000);
}
getTea(function (data) {
console.log(data);
});
getHotpot(function (data) {
console.log(data);
});
现在的奶茶和火锅已经做出来了,但是小明又想先吃火锅,在喝奶茶,这时候我们可以这样做
function getHotpot(fn) {
setTimeout(() => {
fn("火锅");
setTimeout(() => {
fn("奶茶");
}, 2000);
}, 4000);
}
getHotpot(function (data) {
console.log(data);
});
这样可以实现效果,那现在小明又想先吃火锅,在喝奶茶,在去游泳,在去上网,在去健身,在去弹吉他…
我们看下面代码
function getHotpot(fn) {
setTimeout(() => {
fn("火锅");
setTimeout(() => {
fn("奶茶");
setTimeout(() => {
fn("游泳");
setTimeout(() => {
fn("上网");
setTimeout(() => {
fn("健身");
setTimeout(() => {
fn("弹吉他");
}, 2000);
}, 2000);
}, 2000);
}, 2000);
}, 2000);
}, 4000);
}
看这一坨代码头都大了,可维护性实在是很低,这其实就是回调地狱
这个时候,Promise的作用就会显得尤为重要
Promise的使用
Promise是一个对象,我们可以通过创建Promise对象来使用Promise,Promise有两个参数resolve和reject、分别是获取成功和获取失败的结果,获取成功可以返回成功后的数据,获取失败可以返回错误信息,然后使用then方法可以拿到获取成功后的数据
let p = new Promise(resolve => resolve("hello world"));
p.then(data => console.log(data));
解决回调地狱
知道了Promise的基本使用我们就可以解决上面那个栗子回调地狱的问题
function getHotpot() {
return new Promise(resolve => {
setTimeout(() => {
resolve("火锅");
}, 2000);
});
}
function getTea() {
return new Promise(resolve => {
setTimeout(() => {
resolve("奶茶");
}, 1000);
});
}
function gatBodybuilding() {
return new Promise(resolve => {
setTimeout(() => {
resolve("健身");
}, 1000);
});
}
getHotpot()
.then(data => {
console.log(data);
return getTea();
})
.then(data => {
console.log(data);
return gatBodybuilding();
})
.then(data => console.log(data));
这样我们就可以通过返回Promise对象使用then方法来进行链式调用,大大加强了代码的可维护性
解决回调地狱的终极解决方案:Promise语法糖 async await
上面的那种方法虽然已经解决了回调地狱的问题 ,但是凭借朴实的情感和直观的感受并不是很好,所以async await是更好的解决方案
function getHotpot() {
return new Promise(resolve => {
setTimeout(() => {
resolve("火锅");
}, 2000);
});
}
function getTea() {
return new Promise(resolve => {
setTimeout(() => {
resolve("奶茶");
}, 6000);
});
}
function gatBodybuilding() {
return new Promise(resolve => {
setTimeout(() => {
resolve("健身");
}, 1000);
});
}
async function getData() {
let hotpot = await getHotpot();
console.log(hotpot);
let tea = await getTea();
console.log(tea);
let bodybuilding = await gatBodybuilding();
console.log(bodybuilding);
}
getData();
async 函数必须有await ,await接收必须是一个promise对象
这样的代码看起来会更加优雅,可维护性也会非常的高,这也是最开始提到的可以让异步的代码看起来更像是同步的代码。