学会五种获取Promise实例的方法即学会Promise!!!
认识Promise
Promise实例具备的私有属性:
- [[PromiseState]]: "pending":实例状态 "pending":准备(默认) "fulfilled":成功 "rejected":失败
- [[PromiseResult]]: 实例值(结果) Promise.prototype提供一些供实例调用的公共属性方法[Promise实例.xxx()]:
- then
- catch
- finally Promise本身为一个普通对象,拥有一些静态私有属性方法[Promise.xxx()]:
- all
- any
- race
- reject: Promise.reject(xxx)立即创建一个 状态为rejected失败,值是xxx 的promise实例
- resolve: Promise.resolve(xxx)立即创建一个 状态为fulfilled成功,值是xxx 的promise实例
一:new Promise([executor])
let p = new Promise([executor]);
- Promise只能被'new'执行,不能作为普通函数执行
- [executor]必须是个函数,如果不是函数则报错
- 而且new Promise的时候会把[executor]立即执行,并且Promise内部为[executor]传递两个实参,一般都基于resolve和reject两个形参来接收传递的实参信息
- resolve([value]):把实例的状态改为fulfilled,值改为[value] 代表成功的结果
- reject([reason]):把实例的状态改为rejected,值改为[reason] 代表失败的原因
- [executor]函数中的代码,自上而下执行报错,也会修改实例的状态为rejected,值是报错原因
PS:一旦实例的状态从pending状态改为别的状态就不能再次修改为其他状态
let p = new Promise((resolve, reject) => {
resolve('OK');
reject('NO');//一旦实例的状态从pending状态改为别的状态就不能再次修改为其他状态
})
console.log(p);
/*输出:
Promise {<fulfilled>: 'OK'}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: "OK"
*/
二:Promise.reject()/Promise.resolve()
- Promise.reject(xxx)立即创建一个 状态为rejected失败,值是xxx 的Promise实例
- Promise.resolve(xxx)立即创建一个 状态为fulfilled成功,值是xxx 的Promise实例
Promise.resolve('OK') //创建了一个 状态为成功,值为'OK'的实例
Promise.reject('NO') //创建了一个 状态为成功,值为'NO'的实例
三:实例.then/catch/finally()返回一个全新的Promise实例
实例.then([onfulfilled],[onrejected])
- [onfulfilled]方法会在promise实例状态为fulfilled的时候执行
- [onrejected]方法会在promise实例状态为rejected的时候执行 他俩都会把实例的结果([[PromiseResult]])给两个函数
每次执行then方法都会返回一个全新的promise实例 (例如:p2)
- 新实例的状态和值由上一个 '实例'.then 传递进来的[onfulfilled]/[onrejected]方法执行决定
- 方法执行如果报错,则新实例p2状态就是失败,值就是报错的原因
- 方法执行没有报错,则再看方法执行的返回值:
- 如果返回结果是一个Promise实例[用@P表示]: 则@P的状态和值直接影响p2的状态和值
- 如果返回的不是promise实例: 则p2的状态是fulfilled,值是return返回的值(如果没有返回值,则promise实例的值是undefined)
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(100);
}, 1000)
});
let p2 = p1.then(
value => {
console.log('成功', value); //'成功' 100
return Promise.resolve(value * 10); //@P
},
reason => {
console.log('失败', reason);
return Promise.reject(value * 20); //@P
}
);
p2.then(
value => {
console.log('成功', value); // '成功' 1000
},
reason => {
console.log('失败', reason);
}
).then(
value => {
console.log('成功', value);// '成功' undefined
},
reason => {
console.log('失败', reason);
}
);
/*输出:
'成功' 100
'成功' 1000
'成功' undefined
*/
Promise之所这样设计(.then返回新的Promise实例),就是为了实现'THEN链' [实例.then().then()...]
- 'THEN链'具备'穿透/顺延'机制,执行then方法的时候,[onfulfilled]或者[onrejected]可以不传,如果不传,则顺延到下一个等同状态的方法上!!!!!
Promise.reject(100)
.then(
/* value => {
return value;
},
reason => {
throw reason;
} */
) //或者.then(null,null)
.then(
value => {
console.log('成功', value);
},
null)
.then(
null,
reason => {
console.log('失败', reason); // 失败 100
})
.then(
value => {
console.log('成功', value); // 成功 undefined
},
reason => {
console.log('失败', reason);
})
实例.catch()
实例.catch([onrejected]):可以理解为 promise.then(null,[onrejected])
- 真实项目中,一般都是then中只传递onfulfilled方法,在then链末尾加一个catch处理失败的事情,这样不论哪一级出现失败的实例都会顺延到最后的catch中;
- 如果出现失败的Promise实例,而我们并没有基于catch等方法对其进行处理,则会在控制台抛红,虽然不影响代码的执行,但是身为程序员见红则心烦意乱...
Promise.resolve(100).then(value => {
console.log('成功', value); //成功 100
return Promise.reject(value / 10);
}).then(value => {
console.log('成功', value);
return value / 10;
}).then(value => {
console.log('成功', value);
return value / 10;
}).catch(reason => {
console.log('失败', reason); //失败 10
})
实例.finally()
promise.finally([function]):不管是成功还是失败,都会执行
四:Promise.all/any/race([promises])返回一个全新的Promise实例
Promise.all/any/race([promises]):执行方法,传递一个包含零到多个promise实例的集合(promises),返回的结果是一个全新的Promise实例(用@P表示) 如果在promises集合中,某项并不是Promise实例,则会把其默认转换为状态为成功,值为本身值的实例
- all: 集合中每一项都是成功,@P才是成功 (值: 和原始集合相同的顺序,记录每一项成功的结果),只要有一项是失败,则@P就是失败 (值: 当前失败项的值)并且不再往后处理
- any: 集合中只要有一项是成功,@P就是成功 (值: 成功项的值)并且不再往后处理,只有都是失败的,@P才是失败 (AggregateError: All promises were rejected)
- race: 集合中谁先确定成功或失败状态,则@P就以谁的结果为主(哪怕是失败的)
let p1 = Promise.resolve(1);
let p2 = Promise.reject(2);
let p3 = new Promise(resolve => {
setTimeout(() => {
resolve(3)
}, 2000);
});
let p4 = new Promise(resolve => {
setTimeout(() => {
resolve(4)
}, 1000);
});
let p5 = 5; // 转换为 Promise.resolve(5)
let p = Promise.all([p1, p2, p3, p4, p5])
p.then(values => {
console.log('成功', values);
}, reasons => {
console.log('失败', reasons); //失败 2
})
p = Promise.any([p1, p2, p3, p4, p5])
p.then(values => {
console.log('成功', values); // 成功 1
}, reasons => {
console.log('失败', reasons);
})
p = Promise.race([p1, p2, p3, p4, p5])
p.then(values => {
console.log('成功', values); // 成功 1
}, reasons => {
console.log('失败', reasons);
})
五:Promise+Generator的语法糖:async/await
async对函数进行修饰
- 基于async修饰函数,函数默认的返回值会变为一个Promise实例
- 如果函数执行报错,则返回状态为失败,值为报错原因的实例
- 如果本身返回就是一个新的Promise实例,则以自己返回的为主
- 剩下情况则返回状态为成功,值为return返回的值的实例
- 想要在函数中使用await,那么函数必须经过async的修饰 await: let value = await [promise实例]
- await后面必须跟一个promise实例,如果不是则默认转换为状态为成功,值为本身的实例
- await 10 => Promise.resolve(10)
- await会监听后面Promise实例的状态
- 只有实例状态是fulfilled成功,才会把实例值赋值给value,并且当前上下文中await下面的代码才会继续执行[或者理解为: '等待'后面的实例是成功状态,代码才继续执行]
- 如果实例状态是pending/rejected,则当前上下文中,await下面的代码不会执行,也不会给value赋值,只有状态为成功,才会把成功的结果赋值给value,下面代码才会执行
- await异常处理: 如果后面的promise实例是失败,可用try catch的方法进行异常捕获,控制台就不会抛红
基于async修饰的函数,如果函数体中遇到await
- 在await没有处理完之前默认返回 状态是pending值是undefined 的实例
- 等待await处理结果
- 如果await后面实例是失败的,则函数返回的实例也是失败的,值是失败原因
- 如果await后面实例是成功的,则继续执行await下面的代码,而函数返回的实例的状态也要再进一步判断(因为async修饰的函数中可能含有多个await)... 如果整个过程中没有出现报错和失败的实例,则最后函数返回的实例状态是fulfilled,值是函数return的值 总结:async修饰函数的返回值是要依赖函数中await的处理!!
转载自:https://juejin.cn/post/7069792753655218190