Promise的基本概念
promise是什么
promise简单来说是js用于解决异步编程的一种新方案
具体来说promise是一个构造函数,它内部封装异步代码并能获取其结果
promise状态的改变
只能从
pending -> resolved
pending -> rejected
js抛出异常
const p = new Promise((resolve,reject) =>{
setTimeout(()=>{
resolve("该回调成功")
//这时候状态已经由pending -> resolved 所以写了和没写reject一样
reject("失败的回调")
},100)
})
const p2 = new Promise((resolve,reject) =>{
setTimeout(()=>{
throw new Error("失败")
},100)
}).then(null,reason=>console.log(reason))
//抛出异常后 pending -> rejected reason的值就为抛出的值
promise的流程和基本使用
//1.创建promise对象
const p = new Promise((resolve,reject) => {
//2.执行异步代码
setTimeout(()=>{
//3.成功调用resolve失败调用reject
let num = 9
if(num % 2 == 0) resolve("成功!偶数")
else reject("失败!奇数")
},1000)
})
p.then(value => { //成功的值 onResolved
console.log(value)
},reason => { //失败的值 onRejected
console.log(reason)
})
为什么要使用promise
1.使回调函数的定义更加灵活。
我们来看一段代码进行比较
//可以在结果产生之后再调用处理结果的函数
const p = new Promise((resolve,reject) => {
let falg = true
if(falg) resolve("成功了")
else reject("失败了")
})
setTimeout(()=>{
p.then(value => console.log(value),reason => console.log(reason))
},1000)
2.链式调用,解决回调地狱问题的一种方案。
回调地狱
简单理解:回调函数中嵌套回调函数的情况就叫做回调地狱
setTimeout(()=>{
console.log(3);
setTimeout(()=>{
console.log(2);
setTimeout(()=>{
console.log(1);
},1000)
},2000)
},3000)
使用promise的链式调用
new Promise((resolve, reject) => {
resolve(1)
}).then(value => {
console.log(value);
return 2
}).then(value => {
console.log(value);
return 3
}).then(value => {
console.log(value)
}).catch(reason => {
//异常传透,上面代码如果有失败的情况就会执行catch,比纯回调更容易发现问腿
console.log(reason)
})
promise API
1.Promise构造函数
new Promise((resolve,reject)=>{
//同步执行
//成功/失败时调用
//resolve,reject
})
2.Promise.prototype.then
构造函数原型上的then方法给该构造函数的实例使用
有两个参数成功的回调和失败的回调并返回一个新promise对象
3.Promise.prototype.catch
只能传入一个失败的回调
4.Promise.resolve/Promise.reject
//可以产生一个成功/失败的Promise对象
//比如:需求产生一个成功值为1的Promise对象
let p1 = Promise.resolve(1)
p1.then(value => console.log(`成功${value}`),reason => console.log(`失败${reason}`))
5.Promise.all
该方法要求传入一个数组类型的参数,当数组内Promise全部成功时返回成功的回调并把数据放到数组中返回
let p = new Promise((resolve, reject) => {
let falg = true
if(falg) resolve("成功")
else reject("失败")
})
let p1 = Promise.resolve(1)
p1.then(value => console.log(`成功${value}`),reason => console.log(`失败${reason}`))
let p2 = Promise.reject(2)
p2.then(value => console.log(`成功${value}`),reason => console.log(`失败${reason}`))
Promise.all([p,p1]).then(values => {
console.log(values);
},reason => {
console.log(`失败${reason}`);
})
Promise的基本理解
1.一个promise绑定多个成功或者失败的回调都会调用
当一个promise的状态发生改变时,那么他所绑定的相应状态的回调函数都会被执行
const p = new Promise((resolve,reject) => {
resolve(1)
})
p.then(value => {
console.log(value)
},reason => {
console.log(reason)
})
p.then(value => {
console.log(value)
},reason => {
console.log(reason)
})
//此时我们会发现输出了两个1
2.promise的状态改变和指定回调函数谁先谁后
有可能是先改变状态后指定回调函数,也有可能是先指定回调函数后改变状态。一般情况下是先指定的回调函数
这种情况就是先指定的回调函数,因为then是同步执行(里面的回调函数是异步执行)的而状态的改变放到了定时器中模拟异步执行所以是先指定回调函数后改变状态
new Promise((resolve, reject) => {
setTimeout(()=>{
resolve(1)
},100)
}).then(value => {
console.log(value);
})
先改变状态后指定回调函数
new Promise((resolve, reject) => {
//执行器中同步执行
resolve(1)
}).then(value => {
console.log(value);
})
3.promise.then()返回的新promise的状态是由谁决定的?
.then返回的新promise的状态是由then方法所指定的回调函数的执行结果所决定的。
1.如果返回一个非promise的值则新promise为resolved状态并且value值为所返回的值
//如果返回的是非promise的值
new Promise((resolve,reject) => {
resolve(1)
}).then(value => {
//没有抛出异常说明为成功的回调,下面的then也会调用value没有指定返回值的话是undefined
console.log(value)
},reason => {
console.log(reason)
}).then(value => {
console.log(value)
return 23
},reason => {
console.log(reason)
}).then(value => {
console.log(value)
},reason => {
console.log(reason)
})
2.返回一个promise,那所返回的新promise的状态就为返回的promise状态
new Promise((resolve,reject) => {
resolve(1)
}).then(value => {
console.log(value);
return new Promise((resolve, reject) => {
reject(2)
})
/*也可以写成
return Promise.reject(2)
*/
},reason => {
console.log(reason)
}).then(value => {
console.log(value);
},reason => {
console.log(reason)
})
3.如果抛出异常,那所返回的新promise的状态就为rejected,reason的值为抛出的值。
new Promise((resolve,reject) => {
resolve(1)
}).then(value => {
console.log(value);
throw new Error(2)
//也可以写成 throw 2
},reason => {
console.log(reason)
}).then(value => {
console.log(value);
},reason => {
console.log(reason.message)
})
4. promise如何串联多个操作任务?
new Promise((resolve,reject) => {
console.log("执行同步任务1");
resolve(1)
}).then(value => {
console.log("同步任务1的值为",value);
//注意异步任务一定要放到promise中
return new Promise((resolve, reject) => {
setTimeout(()=>{
console.log("开启异步任务1");
resolve(1)
},100)
})
}).then(value => {
console.log("异步任务1的值为",value);
console.log("执行同步任务2");
})
5.异常传透和中断promise链
异常传透
失败的回调,如果then里面都没有回调进行处理的话那么他就会一直向下传传到catch,他是一层一层传下来的所以就叫异常传透
new Promise((resolve, reject) => {
reject(1)
}).then(value => {
console.log(value);
}).then(value => {
console.log(value);
}).catch(reason => {
console.log(reason);
})
就相当与这样写,也可以 reason => Promise.reject(reason) 为什么这里不用括号下面却用了是因为箭头函数不写大括号相当于写了 return。
reason => Promise.reject(reason) == reason => {return Promise.reject(reason)}
new Promise((resolve, reject) => {
reject(1)
}).then(value => {
console.log(value);
},reason => {throw reason}
).then(value => {
console.log(value);
},reason => {throw reason}
).catch(reason => {
console.log(reason);
})
中断promise链使用 new Promise(()=>{})将状态转为pending