ES6–promise方法解决回调地狱问题
要解决回调地狱问题,首先要了解回调地狱的产生是由于早期的javascript只支持回调函数来表现异步操作完成,由于业务逻辑复杂时,就会出现一个串联多个异步操作的问题,而且通常需要多次嵌套回调函数,最经典的比如ajax请求,如下面代码:
let oid
function one(){
$.ajax({//第一个ajax请求,拿到data中的id
url:'http://127.0.0.1:8888/customer/findAll',
method:'get',
success:function(r){
// console.log(r.data[0].id)
oid = r.data[0].id
function two(){
$.ajax({//第二个ajax请求,将第一个ajax请求拿到的id给第二个ajax
url:'http://127.0.0.1:8888/customer/findCustomerById?id='+oid,
method:'get',
success:function(r){
}
})
}
}
})
}
one()
以上第二个ajax请求需要依赖第一个ajax请求得来的id,这时候就要将第二个ajax套在第一个ajax执行成功的方法里面,如果业务逻辑复杂,一层一层依赖多,就会出现多层嵌套关系,也就形成了多次回调,称为回调地狱。而随着代码量增加,嵌套回调的代码出错调bug困难,维护起来十分痛苦。
于是由社区最早提出并且实现了promise方法用来解决回调地狱问题,最终成为了es6新增promise的范本。
如下代码,想要读取三个txt文本文件的内容,但由于javascript的单线程编程性质,所以读取顺序会不固定
book.readFile("./1.txt",'utf-8',function(error,data){
if(error){
throw error;
}
console.log(data);
});
book.readFile('./2.txt','utf-8',function(error,data){
if(error){
throw error;
}
console.log(data);
});
book.readFile('./3.txt',"utf-8",function(error,data){
if(error){
throw error;
}
console.log(data);
})
如果想要固定输出1.txt,2.txt,3.txt,按照以前的写法,就会出现回调地狱,如下代码:
book.readFile("./1.txt",'utf-8',function(error,data){
if(error){
throw error;
}
console.log(data);
book.readFile('./2.txt','utf-8',function(error,data){
if(error){
throw error;
}
console.log(data);
book.readFile('./3.txt',"utf-8",function(error,data){
if(error){
throw error;
}
console.log(data);
})
});
});
期约(promise)解决回调地狱
基础原理
1.es6新增的promise引用类型,可以使用new来实例化
2.promise是一个有状态的对象,
它会处于pedding(待定),resolved(成功后的回调),rejected(失败时的回调)三个状态之一
3.promise抽象的表示一个异步操作,而new一个promise实例代表一个具体的异步操作。
4.promise的prototype原型里有一个then()方法和catch()方法,then()方法用来添加处理程序,catch()方法用来添加拒绝处理程序,而且catch方法其实是一个语法糖,调用它相当于调用Promise.prototype.then(null,onRejected)
5.Promise 创建的实例,是一个异步操作,那么这个异步操作的结果,只能有两种状态:
1:异步执行成功了,需要在内部调用 成功的回调函数 resolve 把结果返回给调用者;
2:异步执行失败了,需要在内部调用 失败的回调函数 reject 把结果返回给调用者;
当使用promise解决时,如下代码
//new三个Promise实例
let bookOne=new Promise(function(resolve,reject){
bookOne.readFile('./1.txt','utf-8',function(r,e){
if(r){
resolve(r);//将pending待定状态变为resolve成功完成状态
}else{
reject(e);//将pending待定状态变为reject拒绝状态
}
})
})
let bookTwo=new Promise(function(resolve,reject){
bookTwo.readFile('./2.txt','utf-8',function(r,e){
if(r){
resolve(r);
}else{
reject(e);
}
})
})
let bookThree=new Promise(function(resolve,reject){
bookThree.readFile('./3.txt','utf-8',function(r,e){
if(r){
resolve(r);
}else{
reject(e);
}
})
})
/* bookOne.then(function(r){//一种写法
console.log(r);
return bookTwo;
}).catch(function(e){
console.log(e);
}).then(function(r){
console.log(r);
return bookThree;
}).catch(function(e){
console.log(e);
}).then(function(r){
console.log(r);
}).catch(function(e){
console.log(e);
}).finally(function(){
console.log('end');
}) */
//第二种写法,利用Promise的all方法
let book = Promise.all([bookOne,bookTwo,bookThree]);
book.then(function(r){
console.log(r)
}).catch(function(e){
console.log(e)
})
优化封装上面代码
function promise(fileArr) {
return new Promise(function (resolve, reject) {
book.readFile(fileArr, 'utf-8', function (r, e) {
if (r) {resolve(r)};
reject(e);
})
});
}
promise('./1.txt')
.then(function (r) {
console.log(r);
return promise('./2.txt')
})
.then(function (r) {
console.log(r);
return promise('./3.txt')
})
.then(function (r) {
console.log(r);
});
.catch(err => {
console.log('error:' + e);
})
以上就是promise解决回调地狱问题的方法。基于个人理解和javascript高级程序设计的阅读,如果有不正确的地方,欢迎大家指正。