promise是什么:
Promise 是 JS 中进行异步编程的新解决方案( 备注:旧方案是单纯使用回调函数)
promise 对象用来封装一个异步操作并可以获取其成功/ 失败的结果值
有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。
异步操作:
事件监听 setTimeout、setInterval Ajax请求 ...
为什么要用 Promise:
1. 指定回调函数的方式更加灵活
旧的: 必须在启动异步任务前指定
promise: 启动异步任务 => 返回 promie 对象 => 给 promise 对象绑定回调函数 (甚至可以在异步任务结束后指定)
2. 支持链式调用, 可以解决回调地狱问题
什么是回调地狱?
回调函数嵌套调用, 外部回调函数异步执行的结果是嵌套的回调函 数执行的条件
回调地狱的缺点? 不便于阅读 / 不便于异常处理
解决方案? promise 链式调用
终极解决方案? async/await
基本使用:
//resolve,reject函数类型的参数
const p=new Promise((resolve,reject)=>{
resolve("成功") //将promise对象状态设为成功
//reject("失败") //将promise对象状态设为失败
})
p.then((value)=>{
console.log(value) //成功执行第一个函数
},(reason)=>{
console.log(reason) //失败执行第二个函数
})
p.catch((reason)=>{
console.log(reason) //单单失败的回调 then()的语法糖
})
//then和cath都是 Promise.prototype上的方法,所以能直接用
promise 的状态改变:
promise的状态:实例对象中的一个属性(PromiseState)
pending未决定的 resolved / fullfilled成功 rejected失败
1. pending 变为 resolved / fullfilled
2. pending 变为 rejected
说明: 只有这 2 种, 且一个 promise 对象只能改变一次 无论变为成功还是失败, 都会有一个结果数据 成功的结果数据一般称为 value, 失败的结果数据一般称为 reason
promise对象的值:
实例对象中的另一个属性(PromiseResult)
保存着对象成功/失败的结果
resolve成功 reject失败
promise 的基本流程:
Promise.resolve 方法:
说明: 返回一个成功/失败的 promise 对象
let p=Promise.resolve(521)
//如果传入参数为非promise类型的值,则返回结果为成功的promise对象,值为参数
console.log(p)// 状态:成功,成功结果:521
----------------------------------------------------------------
//如果传入参数为promise对象,则参数结果决定了它的结果
let p1=Promise.resolve(new Promise((resolve,reject)=>{
reject("失败")
}))
console.log(p1) // 状态:reject,失败结果:失败
//注意:如果返回失败的状态,且没设置失败的回调,浏览器会抛出异常,异常为reject传入的值
Promise.reject 方法:
说明: 返回一个失败的 promise 对象
var p=Promise.reject(521)
console.log(p) //状态:失败 失败结果:521
---------------------------------------------------------------
var p1=Promise.reject(new Promise((resolve,reject)=>{
resolve("成功")
}))
console.log(p1)//状态:失败 失败结果:成功的promise对象
//无论传入什么都是失败,传入什么失败结果就是什么
promise.all 方法:
说明: 返回一个新的 promise, 只有所有的 promise 都成功才成功, 只要有一个失败了就 直接失败
var p=Promise.resolve(521)
var p1=Promise.resolve("ok")
var p2=Promise.resolve("haha")
var p3=Promise.all([p,p1,p2])
console.log(p3)//状态:成功 成功结果:所有promise成功结果组成的数组
-------------------------------------------------------------------------
var p=Promise.resolve(521)
var p1=Promise.reject("error")
var p2=Promise.resolve("haha")
var p3=Promise.all([p,p1,p2])
console.log(p3)//状态:失败 失败结果:失败promise的失败结果
Promise.race 方法:
说明: 返回一个新的 promise, 第一个完成的 promise 的结果状态就是最终的结果状态
var p=Promise.resolve(521)
var p1=Promise.resolve("ok")
var p2=Promise.resolve("haha")
var p3=Promise.race([p,p1,p2])
console.log(p3)//状态:成功 成功结果:p的成功结果521
-----------------------------------------------------------
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("521")
},1000)
})
var p1=Promise.resolve("ok")
var p2=Promise.resolve("haha")
var p3=Promise.race([p,p1,p2])
console.log(p3)状态:成功 成功结果:p1的成功结果ok
如何改变 promise 的状态?
var p=new Promise((resolve,reject)=>{
resolve("成功") //resolve函数修改状态为成功,成功结果为传入的值
reject("失败") //reject函数修改状态为失败,失败结果为传入值
throw "出问题了" //抛出错误可以修改状态为失败,失败结果为写的字符串
})
一个 promise 指定多个成功/失败回调函数, 都会调用吗?
当 promise 改变为对应状态时都会调用
var p=new Promise((resolve,reject)=>{
resolve("成功")
})
p.then((value)=>{
console.log(1) //输出1
})
p.then((value)=>{
console.log(2) //输出2
})
//当 promise 改变为对应状态时都会调用
改变promise状态和指定回调函数谁先谁后?
var p=new Promise((resolve,reject)=>{
resolve("成功")
})
p.then((value)=>{
console.log(value)
})
//当执行器函数里是同步任务时是先改变promise对象状态再指定回调
--------------------------------------------------------------------
var p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("成功");
}, 1000);
});
setTimeout(() => {
p.then((value) => {
console.log(value);
});
}, 2000);
//延迟更长时间才调用 then()时是先改变promise对象状态再指定回调
--------------------------------------------------------------------
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("成功")
},1000)
})
p.then((value)=>{
console.log(value)
})
//当执行器函数里是异步任务时,改变状态需要等一段时间时,是先指定回调再改变promise对象状态
//注意:指定回调不是执行回调函数
什么时候才能得到数据(回调函数什么时候执行)
var p=new Promise((resolve,reject)=>{
resolve("成功")
})
p.then((value)=>{
console.log(value)
})
//如是先改的状态那then方法调用时会立即执行回调函数来处理成功或失败的结果
---------------------------------------------------------------------------
var p=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve("成功")
},1000)
})
p.then((value)=>{
console.log(value)
})
//如果先指定的回调那再改变状态以后再调用成功或失败的结果
promise.then()返回的新 promise 的结果状态由什么决定?
由 then()指定的回调函数执行的返回值决定
var p = new Promise((resolve, reject) => {
resolve("成功");
});
var result=p.then((value) => {
throw "出了问题" //如果抛出异常, 返回状态为 rejected,结果为抛出的异常
});
console.log(result)
---------------------------------------------------------------------------------
var p = new Promise((resolve, reject) => {
resolve("成功");
});
var result=p.then((value) => {
return 1 //如果返回的是非 promise 的任意值, 返回状态为resolved,结果为return的值
});
console.log(result)
注意:如果没有return,则等于return undefined,则返回状态为resolved,结果为undefined
----------------------------------------------------------------------------------
var p = new Promise((resolve, reject) => {
resolve("成功");
});
var result=p.then((value) => {
return new Promise((resolve,reject)=>{
resolve("ok") //如果返回的是另一个新 promise, 返回状态为成功,结果为新promise的结果
})
});
console.log(result)
promise 如何串连多个操作任务?
(1) promise 的 then()返回一个新的 promise, 可以开成 then()的链式调用
(2) 通过 then 的链式调用串连多个同步/异步任务
var p = new Promise((resolve, reject) => {
resolve("ok")
});
p.then((value) => {
return new Promise((resolve,reject)=>{
resolve("成功")
})
}).then((value)=>{
console.log(value) //成功
})
//注意:如何没有写return则是undefined
promise 异常传透?
var p = new Promise((resolve, reject) => {
reject("Err")
});
p.then((value) => {
console.log(1)
}).then((value)=>{
console.log(2)
}).then((value)=>{
console.log(3)
}).catch((reason)=>{
console.warn(reason)
})
//当使用 promise 的 then 链式调用时, 可以在最后指定失败的回调
------------------------------------------------------------------
var p = new Promise((resolve, reject) => {
resolve("ok")
});
p.then((value) => {
throw "失败了"
}).then((value)=>{
console.log(2)
}).then((value)=>{
console.log(3)
}).catch((reason)=>{
console.warn(reason)
})
//前面任何操作出了异常, 都会传到最后失败的回调中处理
如何中断 promise 链?
当使用 promise 的 then 链式调用时, 在中间中断, 不再调用后面的回调函数
var p = new Promise((resolve, reject) => {
resolve("ok")
});
p.then((value) => {
console.log(1)
return new Promise(()=>{}) // 在回调函数中返回一个 pendding 状态的 promise 对象
}).then((value)=>{
console.log(2)
}).then((value)=>{
console.log(3)
}).catch((reason)=>{
console.warn(reason)
})
async 函数:
1. 函数的返回值为 promise 对象
2. promise 对象的结果由 async 函数执行的返回值决定
async function fun(){
return 521
}
let result=fun()
console.log(result) 如果返回值是非promise类型数据,返回状态为成功,结果为return的值
--------------------------------------------------------------------------------
async function fun(){
return new Promise((resolve,reject)=>{
resolve("ok")
})
}
let result=fun()
console.log(result) 如果返回值是promise类型数据,返回状态为返回promise的状态,结果返回promise的状态
---------------------------------------------------------------------------------
async function fun(){
throw "no"
}
let result=fun()
console.log(result) 如抛出异常,返回状态为失败,结果为抛出的值,和返回失败promise效果一样
--------------------------------------------------------------------------------
附加:在JavaScript中,使用Error对象可以来保存有关错误的信息,
例如:
try{
Promise.reject(new Error("no"));
}catch(error){
console.log(error.message) message属性表示错误信息
}
await 表达式:
async函数配合await关键字使用(阻塞代码往下执行),是异步方法,但是阻塞式的
await 是在等待一个 async 函数完成,阻塞后续的执行。
await可以阻塞当前线程,将异步操作变成同步,被阻塞的线程并没有被空闲,而是去执行其他的操作
注意:
1. await 必须写在 async 函数中, 但 async 函数中可以没有 await
2. 如果 await 的 promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理
async function fun(){
let result=await 1
console.log(result) //1
}
fun() //如果右侧是其他类型的值,则右侧是什么就返回什么
-----------------------------------------------------------------
async function fun(){
let p=new Promise((resolve,reject)=>{
resolve("ok")
})
let result=await p
console.log(result) //ok
}
fun() //如果右侧是promise对象,则await会返回promise对象成功的值
-----------------------------------------------------------------
async function fun(){
let p=new Promise((resolve,reject)=>{
reject("no")
})
try{
let result=await p
}catch(e){
console.log(e) //no
}
}
fun() //如果右侧是promise对象且状态为失败,则await会返回抛出错误,需要用try catch进行错误捕获