一、补充
在promise之前,进行异步操作都是单纯使用 “回调函数” 的方法,其中,异步编程主要包含:
1、fs文件操作
2、Ajax
3、定时器
4、数据库操作
二、Promise是什么?
可以理解为一个对象,封装着一个异步操作(未来才结束的事件),并获取操作的结果值(成功与否)。
三、为什么用Promise?
1、指定回调函数方式更灵活:可以在启动异步任务之后给promise对象绑定回调函数,甚至可以在异步任务结束后指定一个很或多个。
2、支持链式调用,解决了回调地狱问题:有了promise对象,可以将异步操作以同步操作的流程表达,并提供统一接口,使得控制异步操作更加容易。
回调地狱:回调函数层层嵌套调用,外部回调函数异步执行的结果是嵌套函数回调执行的条件。回调地狱(代码不断缩进)不便于阅读和异常处理。
--> setTimeout(() => {
console.log(1);
---> setTimeout(() => {
console.log(2);
--> setTimeout(() => {
console.log(3);
}, 3000);
}, 2000);
}, 1000);
四、Promise的状态改变
Promise的状态:是实例对象中的一个属性(PromiseState),对象的状态不受外界影响。promise对象仅代表一个异步操作。
-pending:未决定的、进行中的
-resolved / fullfilled:已成功
-rejected:已失败
promise对象的改变只有两种可能:pending——>resolved、pending——>rejected。一旦状态改变,就不会再变。无论成功还是失败,都会有一个结果数据。
另一个属性(PromiseResult)保存着异步任务 成功/失败 的结果(resolve与reject可以对结果值进行修改)
五、几个API
1、promise构造函数:promise(excutor){},excutor会在promise内部立即同步调用,异步操作在执行器中执行
2、promise.prototype.then方法:指定用于得到成功回调与失败回调,并返回一个新的promise对象
3、promise.prototype.catch:指定用于得到失败回调
4、promise.resolve((value)=>{}):返回一个成功/失败的 promise对象
如果传入参数为 非promise类型的对象,则返回结果为成功的promise对象
如果传入参数为 promise对象,则参数( promise对象)的结果决定了resolve的结果
5、promise.reject((reason)=>{}):reason为失败原因,返回一个失败的promise对象
6、promise.all((promises)=>{}):promises包含n个promise的数组,返回一个新的promise。新promise的结果值PromiseResult数组里包含所有promise的成功结果值(只有所有promise都成功才会成功,一个失败即失败)失败时PromiseResult里仅有失败promise的结果值。
7、promise.race((promises)=>{}):promises包含n个promise的数组,返回一个新的promise。第一个完成的promise的结果状态就是最终的结果状态。
六、相关问题解释
1、如何改变promise状态?
-resolve(value):如果当前是pending会变为resolved
-reject(value):如果当前是pending会变为rejected
-抛出异常:如果当前是pending会变为rejected(throw )
2、一个promise then方法指定多个成功或失败回调函数,都会调用嘛?
-当promise改变为对应状态时 都会调用
let p=new promise((resolve,reject)=>{
resolve('ok')
})
p.then(value=>{
alert(value)
})
p.then(value=>{
console.log(value)
})
3、改变promise状态和指定回调函数的执行先后?
-都可能,正常情况先指定回调再改变状态
-如何先改状态在指定回调?
在执行器中直接调用resolve()、reject()(同步任务)
延迟更长时间才调用then()(进行异步任务时,例如定时器,在定时器回调中执行resolve()、reject()、then())
-什么时候才能得到数据?===回调函数什么时候执行
若先指定的回调,当状态改变时再执行回调函数就会调用,得到数据
若先改变的状态,当指定回调时,回调函数就会调用,得到数据
(简单点说,得resolve跟then都执行了才能拿到数据)
4、promise.then()返回的 新的promise 的结果状态有什么决定?
-由then()指定的回调函数执行的结果决定
- -若抛出异常,新的promise变为rejected,reason为抛出异常
-若返回的是非promise的任意值,新的promise变为resolved,value为返回的值
-若返回的是另一个新promise,此promise的结果就会成为新promise的结果
5、promise如何串联多个操作任务?
-promise的then()返回一个新的promise,可以开成then()的链式调用
-通过then()的链式调用串联多个同步、异步任务
let p=new promise((resolve,reject)=>{
resolve('ok')
})
p.then(value=>{
return new promise((resolve,reject)=>{
resolve('success')
}
}).then(value=>{
console.log(value) //success
}.then(value=>{
console.log(value) //undefined 上一个then无返回值
}
6、promise异常穿透?
-当使用promise的then链式调用的时候,可以在最后指定失败的回调
-前面任何操作出现了异常,都会传到最后失败的回调中
7、中断promise链?
-当使用promise的then链式调用时候,在中间中断,不在调用后面的回调函数、
-办法:再回调函数中返回一个pending状态的promise对象
let p=new promise((resolve,reject)=>{
resolve('ok')
})
p.then(value=>{
console.log(11)
//中断:返回一个pending状态的promise,状态没有再改变,后续的then里的回调不会执行
return new promise(()=>{})
}).then(value=>{
console.log(22)
}).then(value=>{
console.log(33)
}).catch(reason=>{
console.warn(reason)
})
补充:async & await
async函数:函数返回值为promise对象,对象的结果由async函数执行的返回值决定
await表达式:必须在async函数里。await右侧表达式一般为promise对象(返回promise成功的值),也可以为其他值(此值作为await的返回值)
eg:
async function main() {
let p = new Promise((resolve, reject) => {
reject('ooooh')
})
// let res2=await 20
try {
let res3 = await p
} catch (error) {
console.log(error);
}
}main()