什么是回调地狱
回调地狱就是在回调函数中再嵌套回调函数的一种现象。如图
以上只是演示只写了三层,此次也只是为了讲解回调地狱的解决方案,才做此演示,在正常情况下,应该避免回调地狱的出现。
由于在回调函数中嵌套函数就导致代码不易维护,可读性等问题。下面我们就来看一下其解决方案。
解决方案
Promise
什么是Promise
Promise是异步编程的一种解决方案,Promise是一个对象,可以获取异步操作的消息.。
Promise的作用
- 避免回调地狱的问题
它可以解决回调地狱的问题,这也是我们介绍它的原因 - Promise对象提供了简洁的API,使得控制异步操作更加容易
怎么使用Promise
- 创建Promise对象
var promise = new Promise((resolve, reject) => {
setTimeout(function() {
var num = 12;
if (typeof num == "number") {
resolve("ok")
} else {
reject("fail");
}
}, 1000);
});
在构造函数中传入一个函数,该函数需要两个参数,即resolved和rejected函数,在异步事件状态pendding->resolved回调成功时,通过调用resolved函数返回结果;当异步操作失败时,回调用rejected函数显示错误信息。
2. 调用then方法获取执行结果
promise.then((resolve) => {
console.log(resolve);
}, (err) => {
console.log(err);
});
此时我们可以看到在27行输出ok也就是resolve所在的那一行,因此我们可以认为,当函数成功执行后会返回resolve,也就是会执行Promise中的resolve方法并返回传入的参数,如果在执行时遇到错误则会通过err返回,下面我们将num的值改为字符串,此时会报错,那么我们看一下结果
var promise = new Promise((resolve, reject) => {
setTimeout(function() {
var num = "abf";
if (typeof num == "number") {
resolve("ok")
} else {
reject("fail");
}
}, 1000);
});
promise.then((resolve) => {
console.log(resolve);
}, (err) => {
console.log(err);
});
此时通过err输出fail。那么,我们怎么通过Promise解决毁掉地狱的问题呢
function test(time, content) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(content)
});
});
}
我们可以通过一个函数,传入要输出的内容,在Promise中执行异步操作后,返回一个promsie实例对象,然后可以通过这个返回的对象调用then方法,获得返回结果,在then方法中返回再次调用自己定义的方法的结果,如此就解决了回调地狱多层嵌套问题。
test(500, 1).then((resolve) => {
console.log(resolve);
return test(500, 2);
}).then((resolve) => {
console.log(resolve);
});
async和await
async关键字可以将一个函数转换为异步函数。await只能在async函数内使用,await能将异步的函数转换为同步执行函数,从而解决异步函数嵌套问题
async function test(time, content) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(content);
}, time);
});
}
async function demo(){
var result = await test(500,1);//await 将函数转换为同步函数,回调地狱也就不存在了
console.log(result);
var result2 = await test(500,2);
console.log(result2);
}
demo();
此外我们也可以直接在setTimeout函数前使用await
function test(){
return await setTimeout(function(){
console.log(1);
},500);
}
console.log(test);
我们可以从返回结果看出,它反悔的是Promsie对象,也就是对异步操作进行了处理,因此,async和await可以解决回调地狱的问题。