Promise是什么?
- Promise是一个立即执行函数,一旦new ,函数会立即执行
- 立即执行函数有2个参数,成功后调动resolve、失败后调用reject,
- Promise有3个状态,pending、fulfilled、rejected
- Promise上有一个then方法
- 上一个成功后的状态resolve的值会传递给下一个then的成功后的结果,上一个失败后的状态后的结果会传递给下一个reject
- Promise的状态一经改变就无法修改,resolve 或 reject后就无法改变
- Promise链式调用每次都返回一个新的Promise
- 如果Promise返回的是普通值(非Promise非抛错)的情况,会发生值穿透
Promise立即执行
class Promise {
construcotr(executor){
executor();
}
}
module.exprots = Promise;
Promise3种状态
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING;
executor();
}
}
Promise2个参数
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING; // 默认pending态
this.value = null; // 成功后的结果
this.reason = null; // 失败后的结果
const resolve = (value) => {
this.value = value;
}
const reject = (reason) => {
this.reason = reason;
}
executor(resolve,reject);
}
}
Promise的状态无法修改
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING; // 默认pending态
this.value = null; // 成功后的结果
this.reason = null; // 失败后的结果
const resolve = (value) => {
// 只有在pending态的时候才可以将状转变为resolve
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
}
}
const reject = (reason) => {
if(this.status === ONREJECTED){
this.reason = reason;
this.status = ONREJECTED;
}
}
executor(resolve,reject);
}
}
Promise的then方法
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING; // 默认pending态
this.value = null; // 成功后的结果
this.reason = null; // 失败后的结果
this.successCb = []; // 成功后的事件队列
this.failCb = []; // 失败后的事件队列
const resolve = (value) => {
// 只有在pending态的时候才可以将状转变为resolve
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
}
}
const reject = (reason) => {
if(this.status === ONREJECTED){
this.reason = reason;
this.status = ONREJECTED;
}
}
executor(resolve,reject);
},
// then 有2个参数,一个是成功后的回调函数onfulfiled, 一个是失败后的回调函数onrejected
then(onfulfiled,onrejected) {
// 如果此时Promise的状态是成功态,则可以执行成功后的回调
if(this.status === FULFILLED){
onfulfiled();
}
if(this.status === ONREJECTED) {
onrejected();
}
if(this.status === PENDING) {
}
}
}
解决Promise的then方法中的异步问题
通过发布订阅模式,在then中将需要执行的事件放入事件队列,在resolve或reject的时候再一起调用
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING; // 默认pending态
this.value = null; // 成功后的结果
this.reason = null; // 失败后的结果
this.successCb = []; // 成功后的事件队列
this.failCb = []; // 失败后的事件队列
const resolve = (value) => {
// 只有在pending态的时候才可以将状转变为resolve
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
this.successCb.forEach((fn) =>fn()); // resolve时发布之前订阅的异步事件
}
}
const reject = (reason) => {
if(this.status === ONREJECTED){
this.reason = reason;
this.status = ONREJECTED;
this.failCb.forEach(fn => fn());
}
}
executor(resolve,reject);
},
// then 有2个参数,一个是成功后的回调函数onfulfiled, 一个是失败后的回调函数onrejected
then(onfulfiled,onrejected) {
// 如果此时Promise的状态是成功态,则可以执行成功后的回调
if(this.status === FULFILLED){
this.successCb.push(() =>{
onfulfiled();
})
}
if(this.status === ONREJECTED) {
this.failCb.push(() =>{
onrejected();
})
}
if(this.status === PENDING) {
// 如果Promise此时执行的是一个异步事件,则PromisePENDING态说明,需要等待异步时机到达后才能执行
this.successCb.push(() =>{
onfulfiled();
})
this.failCb.push(() =>{
onrejected();
})
}
}
}
Promise的链式调用
链式调用与Jquery中返回this不同的是,Promise是通过返回一个新的Ppromsie实例来实现链式调用
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING; // 默认pending态
this.value = null; // 成功后的结果
this.reason = null; // 失败后的结果
this.successCb = []; // 成功后的事件队列
this.failCb = []; // 失败后的事件队列
const resolve = (value) => {
// 只有在pending态的时候才可以将状转变为resolve
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
this.successCb.forEach((fn) =>fn()); // resolve时发布之前订阅的异步事件
}
}
const reject = (reason) => {
if(this.status === ONREJECTED){
this.reason = reason;
this.status = ONREJECTED;
this.failCb.forEach(fn => fn());
}
}
executor(resolve,reject);
},
// then 有2个参数,一个是成功后的回调函数onfulfiled, 一个是失败后的回调函数onrejected
then(onfulfiled,onrejected) {
const promise2 = new Promise((resolve,reject) => {
// 如果此时Promise的状态是成功态,则可以执行成功后的回调
if(this.status === FULFILLED){
this.successCb.push(() => {
// resvole(x) 将上一次成功后的返回的值传递一个下一个Promsie的resolve
// 如果写成这样在resolvePromise中是获取不到Promise2的,所以需要将下一个Promsise
// 的过程通过异步函数包裹起来
setTimeout(() => {
try {
let x = onfulfiled(this.value);
resolvePromsie(x,promise2,resolve,reject);
} catch(err) {
reject(err);
}
},0)
})
}
if(this.status === ONREJECTED) {
this.failCb.push(() => {
setTimeout(() =>{
try {
let x = onrejected(this.reason);
resolvePromsie(x,promise2,resolve,reject);
} catch(err) {
reject(err);
}
},0)
})
}
if(this.status === PENDING) {
this.successCb.push(() => {
setTimeout(() => {
try {
let x = onfulfiled(this.value);
resolvePromsie(x,promise2,resolve,reject);
} catch(err) {
reject(err);
}
},0)
})
this.failCb.push(() => {
setTimeout(() => {
try {
let x = onrejected(this.reason);
resolvePromsie(x,promise2,resolve,reject);
} catch (err) {
reject(err);
}
},0)
})
}
});
return promise2;
}
}
function resolvePromsie(x,promsie2,resolve,reject){
// 如果上一次的返回值x 与 promise2 是同一个引用,即存在自己等自己执行的情况
if(x == promise2){
return reject(new Error('type error'));
}
if((typeof x !== null && typeof x == 'object') || typeof x === 'function'){
try{
let then = x.then;
// 如果上一次返回的是Promsie, 则继续递归处理,用当前x调用then方法,
if(typeof then === 'function'){
then.call(x,(y) => {
resolvePromsie(y, promsie2,resovle,reject);
},(r) => {
reject(r)
})
} else {
// 如果是普通值,则直接resolve掉
resolve(x);
}
} catch(err) {
reject(err)
}
} else {
resolve(x);
}
}
Promise中resolve或reject的仍然还是Promsie
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING; // 默认pending态
this.value = null; // 成功后的结果
this.reason = null; // 失败后的结果
const resolve = (value) => {
// 如果此时的value仍然是Pormise,则仍需调用value的then方法
if(value instanceof Promsie){
value.then(resolve,reject);
}
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
}
}
const reject = (reason) => {
// 如果此时reason的类型仍然是Pormise,则仍需调用reason的then方法
if(reason instanceof Promise){
reason.then(resolve,reject);
}
if(this.status === ONREJECTED){
this.reason = reason;
this.status = ONREJECTED;
}
}
executor(resolve,reject);
}
}
完整版实现
Promise中resolve或reject的是普通值
const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const ONREJECTED = 'onrejected';
class Promise {
constructor(executor){
this.status = PENDING; // 默认pending态
this.value = null; // 成功后的结果
this.reason = null; // 失败后的结果
this.successCb = []; // 成功后的事件队列
this.failCb = []; // 失败后的事件队列
const resolve = (value) => {
// 只有在pending态的时候才可以将状转变为resolve
if(this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
this.successCb.forEach((fn) =>fn()); // resolve时发布之前订阅的异步事件
}
}
const reject = (reason) => {
if(this.status === ONREJECTED){
this.reason = reason;
this.status = ONREJECTED;
this.failCb.forEach(fn => fn());
}
}
executor(resolve,reject);
},
// then 有2个参数,一个是成功后的回调函数onfulfiled, 一个是失败后的回调函数onrejected
then(onfulfiled,onrejected) {
// 如果上一次的返回值x是一个普通值,会发生值得穿透
onfulfiled = typeof x == 'object' ? onfulfiled : v=>v;
onrejected = typeof x == 'object' > onrejected : reject(){throw new Error()};
const promise2 = new Promise((resolve,reject) => {
// 如果此时Promise的状态是成功态,则可以执行成功后的回调
if(this.status === FULFILLED){
this.successCb.push(() => {
// resvole(x) 将上一次成功后的返回的值传递一个下一个Promsie的resolve
// 如果写成这样在resolvePromise中是获取不到Promise2的,所以需要将下一个Promsise
// 的过程通过异步函数包裹起来
setTimeout(() => {
try {
let x = onfulfiled(this.value);
resolvePromsie(x,promise2,resolve,reject);
} catch(err) {
reject(err);
}
},0)
})
}
if(this.status === ONREJECTED) {
this.failCb.push(() => {
setTimeout(() =>{
try {
let x = onrejected(this.reason);
resolvePromsie(x,promise2,resolve,reject);
} catch(err) {
reject(err);
}
},0)
})
}
if(this.status === PENDING) {
this.successCb.push(() => {
setTimeout(() => {
try {
let x = onfulfiled(this.value);
resolvePromsie(x,promise2,resolve,reject);
} catch(err) {
reject(err);
}
},0)
})
this.failCb.push(() => {
setTimeout(() => {
try {
let x = onrejected(this.reason);
resolvePromsie(x,promise2,resolve,reject);
} catch (err) {
reject(err);
}
},0)
})
}
});
return promise2;
}
}
function resolvePromsie(x,promsie2,resolve,reject){
// 如果上一次的返回值x 与 promise2 是同一个引用,即存在自己等自己执行的情况
if(x == promise2){
return reject(new Error('type error'));
}
if((typeof x !== null && typeof x == 'object') || typeof x === 'function'){
try{
let then = x.then;
// 如果上一次返回的是Promsie, 则继续递归处理,用当前x调用then方法,
if(typeof then === 'function'){
then.call(x,(y) => {
// 此时将上一次成功后的返回值y,传递给下一个处理函数
resolvePromsie(y, promsie2,resovle,reject);
},(r) => {
reject(r)
})
} else {
// 如果是普通值,则直接resolve掉
resolve(x);
}
} catch(err) {
reject(err)
}
} else {
resolve(x);
}
}
Promise的链式调用应用
1.如果当前promsie返回的不是promise,则会将成功或者失败后的值,传递给外层的then,(失败返回undefned)也会进入外层then的成功
function read(...args) {
return new Promise((resolve,reject) => {
fs.readFile(...args,(err,data) => {
if(err) console.log(err)
resolve(data)
})
})
}
read('./name.txt','utf8').then(data => {
return 100;
},err =>{
console.log(err)
})
.then((data) => {
console.log(data)
})
- 如果读取成功,传入外层的then的data里面
- 如果读取失败,则console.log(err)返回的是undefined,还是会将undefined传入到data中
2.如果当前promise执行出错了,抛出异常,则会走当前的失败,如果当前没有失败,则会走外层的失败,外层没有失败,则会走catch
read("./name1.txt").then((res) => {
throw new Error('err')
},(err) => {
console.log("err1",err)
}).then(res => {
console.log(res)
},(err) => {
console.log("err2",err)
}).catch(err => {
console.log('catch',err)
})
- 如果当前返回的是Promise,则会将当前的promise的执行后的结果作为下一次then的then的成功或失败
read("./name.txt","utf8").then((res ) => {
return read("./age.txt",'utf8')
},err => {
console.log("err1",err)
}).then(data => {
console.log('s',data)
},(err) => {
console.log('err2',err)
})
什么时候当前的then走完了,会走下一次then的失败?
- then中抛出异常
- 返回的promise执行出错了(栗子3中的,读取age文件出错了),会被外层的err2捕捉到