一、promise 的介绍
1.实例对象中的属性:
new promise()或者Promise.resolve等都会返回一个promise实例对象。
promise需要有值来表示当前的状态,后续then中的需要根据状态来决定执行哪个函数
pending表示未决定,初始状态,可以转变为成功或失败,但只能转一次。
resolve() 方法:调用resolve方法,状态将由pending 变为 fullfilled,表示成功,并且可以设置返回值如,resolve(123)
reject()或者throw:调用reject方法,状态将由pending 变为 rejected,表示失败,并且可以设置返回值如,reject(123)
状态成功就执行后续then里面的第一个函数,失败就执行第二个函数,并且在函数中接收resolve或者reject返回的值。
2.promise对象的值:
1.promise实例对象中的PromiseResult属性保存着任务成功或失败的结果。
2.promise实例对象中的PromiseState保存着状态,成功或失败,即fulfilled或rejected
3.改变promise状态和指定回调函数谁先谁后?
(1)都有可能,正常情况下是先指定回调再改变状态,但也可以先改状态在指定回调。
(2)如何先改状态再指定回调:
在执行器函数中直接调用resolve()/reject()
延迟更长时间才调用
(3)什么时候得到数据
如果执行器函数中是异步任务,那么先调用then(),等异步任务执行完状态改变时,回调函数就会调用得到数据。
如果执行器函数中是同步任务,那么同步函数执行完改变状态后回调函数再,得到数据
4.promise如何串联多个任务
promise的每一个then()都返回一个新的promise,可以开成then()的链式调用
通过then的链式调用串联多个同步/异步任务
5.关于then方法的几个问题
new Promise(function (resolve, reject) {
console.log(1111);
resolve(2222);
}).then(function (value) {
console.log(value);
return 3333;
}).then(function (value) {
console.log(value);
throw "An error";
}).catch(function (err) {
console.log(err);
});
这里的输出结果是
1111
2222
3333
An error
因为then里面都是同步的代码,先return,再执行后续的then
new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('1111111')
}, 1000)
})
.then(function (value) {
setTimeout(function () {
console.log('输出上一个定时器的返回结果:', value)
return '22222222'
}, 1000)
})
.then(function (value) {
setTimeout(function () {
console.log('输出上一个定时器的返回结果:', value)
}, 1000)
})
这里输出的是
输出上一个定时器的返回结果:1111111
输出上一个定时器的返回结果:undefined
因为,第一个的then会等resolve的返回结果,但是,第二个then不会等第一个then中return的结果
如果想要第二个then等待第一个then的结果,需要在第一个then中return一个promise实例并resolve或者reject,并且异步内容要写在promise实例的函数中,例如:
new Promise(function (resolve, reject) {
setTimeout(function () {
resolve('1111111')
}, 1000)
})
.then(function (value) {
return new Promise((resolve, reject) => {
setTimeout(function () {
console.log('输出上一个定时器的返回结果:', value)
resolve('2222')
}, 1000)
})
})
.then(function (value) {
console.log('输出上一个定时器的返回结果:', value)
})
6.then方法返回值结果状态由什么决定?
由then中执行的回调函数决定。
如果then中的回调函数抛出异常,新promise的PromiseState变为rejected,PromiseResult为抛出的异常的结果。
如果then中的回调函数返回的是非promise值,新的promise的PromiseState变为resolved,PromiseResult为该返回的值。
如果then中的回调函数返回的是一个promise对象,则新的promise的状态和结果为该promise的状态和结果。
var p = Promise.resolve(1)
p.then((value)=>{
//1、返回一个Promise 调用resolve
新建promise的resolve传出的值将作为then方法返回的promise的resolve的值传递出
return new Promise(function(resolve,rejected){
resolve(value + 1)
})
//2、返回一个Promise 调用rejected
新建promise的reject传出的值将作为then方法返回的promise的reject的值传递出
return new Promise(function(resolve,rejected){
rejected(value + 1)
})
//3、返回一个值
return的值将作为then方法返回的promise的resolve的值传递出
return value + 1;
以下四、五、六种情况,then方法的函数没有返回值,导致下一个then的resolve参数是undfined
//4、新建一个promise,使用reslove返回值
const newp = new Promise(function(resolve,rejected){
resolve(value + 1)
})
//5、新建一个promise,使用return返回值
const newp = new Promise(function(resolve,rejected){
return(value + 1)
})
//6、没有返回值
return undefined
}).then((value)=>{
console.log("情况{n}:resolve",value)
}, (res) => {
console.log("情况{n}:reject", res);
})
7.异常穿透
当使用promise的then链式调用时,可以在最后指定失败的回调
前面任何操作出了异常,都会传到最后失败的回调中
8.如何中断promise链:
当使用promise的then链式调用时,在中间中断,不再调用后面的回调函数
办法:在回调函数中返回一个pendding状态的promise对象,即在需要中断的then中返回一个pendding状态的promise对象
二、 Promise相关的API的使用
1.promise的构造函数,会在promise内部立即同步调用,异步操作在执行器中执行。
var p = new Promise(function(){
console.log('11')
resolve('成功')
}.then( function(data){
console.log(data)
}
2.resolved方法,是函数对象的方法
//如果传入的参数为非Promise对象,则返回的结果为成功的Promise对象
var p1 = Promise.resolve(423);
//如果传入的参数为Promise对象,则传入的参数结果决定了resolve的结果,
//如果传入的参数成功,则resolve为参数的resolve值;如果传入的参数失败,则reject为参数的reject值
var p1 = Promise.resolve(new Promise(function(resolve,reject){
reject(err);
resolve('正常返回!!!');
}));
3.reject方法,也是函数对象的方法
//无论在reject内传入什么,返回的结果都是失败,传入的是什么失败的结果就是什么
var p1 = Promise.reject(423);
var p1 = Promise.reject(new Promise(function(resolve,reject){
// reject(err);
resolve('正常返回!!!');
}));
4.all方法
参数为多个promise实例对象组成的数组,返回一个新的promise对象,只有数组中所有的promise对象都成功才成功,只要有一个失败了就失败。
如果成功,新的promise对象的成功结果为数组中所有promise对象成功的结果组成的数组。
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: Array(3)
var p1 = new Promise(function(resolve,reject){
resolve("ojbk");
})
var p2 = Promise.resolve('yes');
var p3 = Promise.resolve('ok');
const result = Promise.all([p1,p2,p3]);
console.log(result);
如果失败,新的promise对象的失败结果为数组中第一个失败的对象失败的结果。
[[PromiseState]]: "rejected"
[[PromiseResult]]: "FAILED"
var p1 = new Promise(function(resolve,reject){
resolve("ojbk");
})
var p2 = Promise.resolve('yes');
var p3 = Promise.reject('FAILED');
const result = Promise.all([p1,p2,p3]);
console.log(result);
5.race方法
参数为多个promise对象组成的数组,返回值为一个新的promise对象,结果为第一个改变的promise对象的结果。
var p1 = new Promise(function(resolve,reject){
resolve("ojbk");
})
var p2 = Promise.reject('yes');
var p3 = Promise.reject('FAILED');
const result = Promise.race([p1,p2,p3]);
console.log(result);
结果为:
[[PromiseState]]: "rejected"
[[PromiseResult]]: "yes"
三、async和await
async函数
添加async的函数,返回值是一个promise对象。返回的promise对象的结果,由return的结果决定,规则和then返回规则相同。
如果return非promise对象:
如 async function getInfo() {
...其他代码
return 321
}
那么调用getInfo返回的promise对象的PromiseResult等于321,PromiseState为fulfilled
如果return promise对象
如 async function getInfo() {
...其他代码
return new Promise(function (resolve,reject) {
resolve('成功了')
})
}
那么返回的promise对象的PromiseResult='成功了',PromiseState=fulfilled
await表达式
await右侧的表达式一般为promise对象,但也可以是其他值。
如果表达式是promise对象,await返回的是promise成功的值。
如果await的promise函数失败了,就会抛出异常,需要通过try...catch捕获
如果表达式是其他值,直接将此值作为await的返回值。
await该行后面的代码都是微任务
await必须写在async函数中,而async函数中可以没有await。