JavaScript高级手记 ( Promise详解
/*
* 创建Promise实例的时候得传一个函数 executor,并且这个函数接收两个参数
+ resolve函数:将实例的状态从 pending 修改为 fulfilled/resolved,同时将实例的值改为执行这个函数时传递的实参
+ reject函数:将实例的状态从 pending 修改为 rejected,同时将实例的值改为执行这个函数时传递的实参
每一个Promise实例都有两个重要的属性:
+ [[PromiseState]] 实例的状态
+ pending 初始状态
+ 通过new创建实例的时候,没有在executor函数中执行resolve函数,也没有执行reject函数,则创建的实例状态为pending,值为undefined
+ 通过 实例1.then() 执行then函数时,没有给then函数传递A函数和B函数,则返回的新实例的状态为pending,值为实例1的结果
+ fulfilled/resolved 成功状态
+ rejected 失败状态
注意:实例的状态是单向改变的,即只能从pending变为fulfilled/resolved,或者从pending变为rejected
+ [[PromiseResult]] 实例的结果/值
+ undefined 初始值
+ 成功的结果/失败的原因
*/
let p1 = new Promise((resolve, reject) => {
resolve(100);
reject(200); // 这里不会执行,因为执行完 resolve(100) 后实例的状态已经从pending改为fulfilled了
});
console.dir(p1); // 状态为 fulfilled,值为 100
/*
* 实例可以调用其所属类的原型上的方法,Promise也一样
* Promise.prototype上的方法:
+ then(A, B):then方法跟executor函数一样,接收两个函数 A和B
+ A(res)函数:
接收一个参数res,如果当前实例的状态为 fulfilled/resolved 则执行它,且 res 的值为当前实例的结果/值
+ B(rej)函数:
接收一个参数 rej,如果当前实例的状态为 rejected 则执行它,且 rej 的值为实例的结果/值
+ catch
+ finally
*/
let p1 = new Promise((resolve, reject) => {
resolve(100);
});
let p2 = p1.then(res=>{
console.log(res); // 100
}, rej=>{
console.log(rej)
});
// 通过 实例.then() 执行then方法之后会返回一个新的 Promise 实例
console.log(p2); //一个新的实例
/*
* 执行 实例1.then 函数返回一个新的实例,新的实例2的状态和值怎么确定?
+ 实例2的状态:
1、如果在执行时没有给then传递A函数和B函数,那实例2的状态为pending
2、实例1.then(A,B);不论then中执行的是A函数还是B函数,只要不报错,那实例2的状态就为 fulfilled;如果报错,实例2的状态则为 rejected
+ 实例2的结果/值
1、如果实例2的状态为 pending,则实例2的值跟实例1的一样
2、如果实例2的状态为 fulfilled/resolved,那实例2的值是实例1基于then函数中执行A或执行B返回的结果
特殊情况:如果函数A或者函数B中返回的是一个新的Promise实例,那return的实例的状态以及结果,直接决定实例2的状态和结果
3、如果实例2的状态为 rejected,那实例2的结果/值就是失败的原因
实例1的状态和值也受 executor 函数执行的影响
+ 如果执行 executor 函数报错了,则实例的是状态为 rejected,值为报错的原因
+ 如果执行 executor 函数没有报错,那要看executor函数中执行的是 resolev函数还是rejecte函数
*/
let p1 = new Promise((resolve, reject) => {
resolve(100);
reject(200); // 这里不会执行,因为执行完 resolve(100) 后实例的状态已经从pending改为fulfilled了
});
console.dir(p1); // 状态为 fulfilled,值为 100
let p2 = p1.then(res=>{
// return 400; // 实例p2的状态为 fulfilled,值为 400
// 返回一个状态为pending,值为undefined的实例
return new Promise(()=>{}); // p2的状态为 pending,值为undefined
}, rej=>{
});
/*
* Promise作为内置类,也是一个对象,也有自己的私有方法(只能通过Promise.xxx()调用)
+ resolve([val]):快速创建一个状态为成功,值为val的实例
+ rejecte([val]):快速创建一个状态为失败,值为val的实例
+ all():
+ race():
*/
let p1 = Promise.resolve(100); // p1的状态为 fulfilled,值为 100
let p2 = Promise.reject(400); // p2的状态为 rejected,值为 400
/*
* then([A],[B]):如果其中一个函数没有传递,则会“顺延”
+ [A]没有传递:则找下一个 then 中的 A 函数
+ [B]没有传递:则找下一个 then 中的 B 函数
*/
// 成功的顺延:如果then中没有传A函数,默认会执行 res=>{return res}
Promise.resolve(200).then(null/!* res =>{return res} *!/, rej=>{
console.log('我是第一个then中的B函数')
}).then(res=>{
console.log('我是第二个then中的A函数', res)
}, rej=>{
console.log('我是第二个then中的B函数', rej);// 404
});
// 失败的顺延:如果then中没有传B函数,默认会执行 rej=>{return Promise.reject(rej)}
Promise.reject(404).then(res=>{
console.log('第一个then中的A函数', res)
},/!* rej=>{return Promise.reject(rej)} *!/).then(res=>{
console.log('我是第二个then中的A函数', res)
}, rej=>{
console.log('我是第二个then中的B函数', rej);// 404
});
// catch:等价于 then(null,rej=>{...})
Promise.reject(10).then(res=>{
console.log('成功了', res)
}).then(res=>{
console.log('我是第二个then')
}).catch(rej =>{
console.log('失败了', rej); // 输出 10
});
// 真实项目中:then只是处理成功,即只传一个A函数;catch处理失败(传B函数),且通常将catch写在末尾
// 返回失败状态的实例,但是没有做失败处理,浏览器控制台有报错(但是不影响其他代码的执行)
/* Promise.reject(10).then(res=>{
console.log(res)
}); // 浏览器中会有报错 */
// 如果加上catch,哪怕什么都不做,浏览器也不报错了
Promise.reject(10).then(res=>{
console.log('成功');
}).catch(rej=>{}); // 不报错了