promise简述
promise用途(为什么用promise):
*使用链式调用
return new promise(为什么要返回一个API,再是.then)
promise用途:自己约定的名字不够规范、回调地狱处理–第一种是为了可控(多了.then)通过.then知道success是第几个参数,第二种则是promise提供了链式操作,好处是可以让异步操作就像同步操作一样,不必一层层地嵌套回调函数。
1)回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象,代码臃肿,可读性差,回调地狱是缩进多,而promise可通过then来保持缩进.then
.then
2)promise可以支持多个并发的请求,获取并发请求中的数据
2)难进行错误处理(try catch):settimeout(()=>{})不能触发try catch
3)*Promise 并不能消灭回调地狱(还是有缩进),但是它可以使回调变得可控(能确定 success2 是第几个参数、链式操作:看上去像同步操作)
Promise 可以让异步操作写起来就像同步操作一样,不必一层层地嵌套回调函数。
getGroup(response.id, success2, error2) //无用promise
getGroup(response.id).then(success2, error2) //用promise
setTimeout(function () { //第一层
console.log('武林要以和为贵');
setTimeout(function () { //第二程
console.log('要讲武德');
setTimeout(function () { //第三层
console.log('不要搞窝里斗');
}, 1000)
}, 2000)
}, 3000)
//武林要以和为贵
//要讲武德
//不要搞窝里斗
回调地狱就是为实现异步代码顺序执行而出现的一种操作
promise的解决方案:
function fn(str){
var p=new Promise(function(resolve,reject){
//处理异步任务
var flag=true;
setTimeout(function(){
if(flag){
resolve(str)
}
else{
reject('操作失败')
}
})
})
return p;
}
fn('武林要以和为贵')
.then((data)=>{
console.log(data);
return fn('要讲武德');
})
.then((data)=>{
console.log(data);
return fn('不要搞窝里斗')
})
.then((data)=>{
console.log(data);
})
.catch((data)=>{
console.log(data);
})
promise.then 中的函数是异步执行的,但不按下图这种.then嵌套.then写法,是因为没必要。
Promise的链式编程可以保证代码的执行顺序,每一次在then做完处理后,会return一个Promise对象,这样能在下一次then时接收到数据,保证代码顺序。
.then.then…和.then嵌套都是使异步代码顺序执行,但得看是否同个对象,同个对象可以用.then.then链式,不同对象.then嵌套。
Promise不管什么操作都用then,就会导致一眼看过去全是then…then…then…,这样也是不利于代码维护的。
所以通过async/await 可以使代码看起来更像同步代码。
回调有三个问题:1、自己约定的名字不够规范 2、难进行try catch错误处理(比如setTimeout) 3、容易有回调地狱
回调地狱是什么:
function getUser(successCallback, errorCallback){
$.ajax({
url:'/user',
success: function(response){
successCallback(response)
},
error: function(xhr){
errorCallback(xhr)
}
})
}
如果我们获取用户数据之后还要获取分组数组、分组详情等
getUser(function(response){
getGroup(response.id, function(group){
getDetails(groupd.id, function(details){
console.log(details)
},function(){
alert('获取分组详情失败')
})
}, function(){
alert('获取分组失败')
})
}, function(){
alert('获取用户信息失败')
})
用了promise后又是怎么解决的:
1、获取分组信息
getUser().then(function(response){
getGroup(response.id).then(function(group){
getDetails(group.id).then(function(){
},error3)
},error2)
}, error1)
*Promise 并不能消灭回调地狱,但是它可以使回调变得可控
getGroup(response.id, success2, error2) //无用promise
getGroup(response.id).then(success2, error2) //用promise
用 Promise 之前,你不能确定 success2 是第几个参数;
getUser(function(response){
getGroup(response.id, function(group){
getDetails(groupd.id, function(details){
console.log(details)
},function(){
alert('获取分组详情失败')
})
}, function(){
alert('获取分组失败')
})
}, function(){
alert('获取用户信息失败')
})
用 Promise 之后,所有的回调都是.then(success, error)
getUser().then(function(response){
getGroup(response.id).then(function(group){
getDetails(group.id).then(function(){
},error3)
},error2)
}, error1)
2、在用户信息获取结束后做更多事
var promise = getUser()
promise.then(successCallback, errorCallback)
当用户信息加载完毕,successCallback 和 errorCallback 之一就会被执行。
相当于:
getUser().then(successCallback, errorCallback)
如果你想在用户信息获取结束后做更多事,可以继续 .then:
getUser().then(success1).then(success2).then(success3)
请求成功后,会依次执行 success1、success2 和 success3。
*使用链式调用
promise是什么:
1、Promise是一个对象,用来解决异步问题,可以让异步操作写起来就像同步操作一样,不必一层层地嵌套回调函数。
有三种状态,pending(进行中)、resolved(已完成)、r ejected(已失败)。 当Promise的状态由pending转变为resolved或reject时,会执行相应的方法
2、Promised的特点是只有异步操作的结果,可以决定当前是哪一种状态,任务其他操作都无法改变这个状态,也是“Promise”的名称的由来,同时,状态一旦改变,就无法再次改变状态
promise缺点
不能取消请求,可通过Axios解决
promise用法
代码 Promise 用法
function f1(resolve, reject) {
// 异步代码...
}
var p1 = new Promise(f1);
上面代码中,Promise构造函数接受一个回调函数f1作为参数,f1里面是异步操作的代码。然后,返回的p1就是一个 Promise 实例。
回调函数:当一个函数作为参数传入另一个参数中,它不会立即执行,只有当满足一定条件后该函数才可以执行(Ajax:咖啡好了,服务员通知、定时器:时间到)
Promise 实例有一个then方法,用来指定下一步的回调函数。
var p1 = new Promise(f1);
p1.then(f2);
上面代码中,f1的异步操作执行完成,就会执行f2。
传统的写法可能需要把f2作为回调函数传入f1,比如写成f1(f2),异步操作完成后,在f1内部调用f2。Promise 使得f1和f2变成了链式写法。不仅改善了可读性,而且对于多层嵌套的回调函数尤其方便。(此处返回的Promise 实例依然是p1)