promise声明
首先呢,promise肯定是一个类,我们就用class来声明。
• 由于 new Promise((resolve, reject)=>{}) ,所以传入一个参数(函数),executor,传入就执行。
•executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。
•由于resolve和reject可执行,所以都是函数
•Promise存在三个状态(state)pending、fulfilled、rejected
•pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)
•成功时,不可转为其他状态,且必须有一个不可改变的值(value)
•失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)
• new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。
• new Promise((resolve, reject)=>{reject(reason)}) reject为失败,接收参数reason,状态改变为rejected,不可再次改变。
•若是executor函数报错 直接执行reject();
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
// 生成器
constructor(executor) {
// executor 立即执行
// 成功执行 resolve或reject
try {
executor(this.resolve, this.reject);
} catch (e) {
//失败执行reject
this.reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为失败
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
}
then 方法
Promise有一个叫做then的方法,里面有两个参数:onFulfilled,onRejected,成功有成功的值,失败有失败的原因
•当状态state为fulfilled,则执行onFulfilled,传入this.value。当状态state为rejected,则执行onRejected,传入this.value
•onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数
then(successCallback, failCallback) {
// 同步情况下成功时执行成功回调
if (this.status === FULFILLED) {
successCallback(this.value);
// 同步情况下失败时执行失败回调
} else if (this.status === REJECTED) {
failCallback(this.reason);
}
}
解决异步实现
现在基本可以实现简单的同步代码,但是当resolve在setTomeout内执行,then时state还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
类似于发布订阅,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内。
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
// 生成器
constructor(executor) {
// executor 立即执行
// 成功执行 resolve或reject
try {
executor(this.resolve, this.reject);
} catch (e) {
//失败执行reject
this.reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在 调用
while (this.successCallback.length) {
this.successCallback.shift()();
}
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为失败
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断成功回调是否存在 如果存在 调用
while (this.failCallback.length) {
this.failCallback.shift()();
}
};
then(successCallback, failCallback) {
if (this.status === FULFILLED) {
// 回调的函数是否异步
successCallback(this.value);
// 同步情况下失败时执行失败回调
} else if (this.status === REJECTED) {
failCallback(this.reason);
//异步情况下执行
} else {
// onFulfilled传入到成功数组
this.successCallback.push(() => {
successCallback(this.value);
});
// onRejected传入到失败数组
this.failCallback.push(() => {
failCallback(this.reason);
});
}
});
}
解决链式调用
我门常常用到 new Promise().then().then() ,这就是链式调用,用来解决回调地狱
1、为了达成链式,我们默认在第一个then里返回一个promise。秘籍规定了一种方法,就是在then里面返回一个新的promise,称为promise2: promise2 = new Promise((resolve, reject)=>{})
•将这个promise2返回的值传递到下一个then中
•如果返回一个普通的值,则将普通的值传递给下一个then中
2、当我们在第一个then中 return 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值
秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
// 生成器
constructor(executor) {
// executor 立即执行
// 成功执行 resolve或reject
try {
executor(this.resolve, this.reject);
} catch (e) {
//失败执行reject
this.reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在 调用
while (this.successCallback.length) {
this.successCallback.shift()();
}
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为失败
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断成功回调是否存在 如果存在 调用
while (this.failCallback.length) {
this.failCallback.shift()();
}
};
then(successCallback, failCallback) {
let promise2 = new MyPromise((resolve, reject) => {
// 同步情况下成功时执行成功回调
if (this.status === FULFILLED) {
// 回调的函数是否异步
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
// 同步情况下失败时执行失败回调
} else if (this.status === REJECTED) {
try {
let x = failCallback(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
//异步情况下执行
} else {
// onFulfilled传入到成功数组
this.successCallback.push(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
// onRejected传入到失败数组
this.failCallback.push(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
});
}
});
return promise2;
}
}
完成resolvePromise函数
秘籍规定了一段代码,让不同的promise代码互相套用,叫做resolvePromise
•如果 x === promise2,则是会造成循环引用,自己等待自己完成,则报“循环引用”错误
let p = new Promise(resolve => {
resolve(0);
});
var p2 = p.then(data => {
// 循环引用,自己等待自己完成,一辈子完不成
return p2;
})
1、判断x
• Otherwise, if x is an object or function,Let then be x.then
•x 不能是null
•x 是普通值 直接resolve(x)
• x 是对象或者函数(包括promise), let then = x.then 2、当x是对象或者函数(默认promise)
•声明了then
•如果取then报错,则走reject()
•如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调
•如果成功的回调还是pormise,就递归继续解析 3、成功和失败只能调用一个 所以设定一个called来防止多次调用
function resolvePromise(promsie2, x, resolve, reject) {
if (promsie2 === x) {
return reject(new TypeError('Chaining cycle detected for promis'));
}
if (x instanceof MyPromise) {
// promise 对象
x.then(
(value) => resolve(value),
(reason) => reject(reason)
);
} else {
// 普通值
resolve(x);
}
}
解决其他问题
1、秘籍规定onFulfilled,onRejected都是可选参数,如果他们不是函数,必须被忽略
• onFulfilled返回一个普通的值,成功时直接等于 value => value
• onRejected返回一个普通的值,失败时如果直接等于 value => value,则会跑到下一个then中的onFulfilled中,所以直接扔出一个错误 reason => throw err 2、秘籍规定onFulfilled或onRejected不能同步被调用,必须异步调用。我们就用setTimeout解决异步问题
•如果onFulfilled或onRejected报错,则直接返回reject()
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
// 生成器
constructor(executor) {
// executor 立即执行
// 成功执行 resolve或reject
try {
executor(this.resolve, this.reject);
} catch (e) {
//失败执行reject
this.reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在 调用
while (this.successCallback.length) {
this.successCallback.shift()();
}
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为失败
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断成功回调是否存在 如果存在 调用
while (this.failCallback.length) {
this.failCallback.shift()();
}
};
then(successCallback, failCallback) {
// successCallback如果不是函数,就忽略successCallback,直接返回value
successCallback = successCallback ? successCallback : (value) => value;
// failCallback如果不是函数,就忽略failCallback,直接扔出错误
failCallback = failCallback
? failCallback
: (reason) => {
throw reason;
};
let promise2 = new MyPromise((resolve, reject) => {
// 同步情况下成功时执行成功回调
if (this.status === FULFILLED) {
// 回调的函数是否异步
setTimeout(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
// 同步情况下失败时执行失败回调
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
//异步情况下执行
} else {
// onFulfilled传入到成功数组
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// onRejected传入到失败数组
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
}
function resolvePromise(promsie2, x, resolve, reject) {
if (promsie2 === x) {
return reject(new TypeError('Chaining cycle detected for promis'));
}
if (x instanceof MyPromise) {
// promise 对象
x.then(
(value) => resolve(value),
(reason) => reject(reason)
);
} else {
// 普通值
resolve(x);
}
}
catch
catch(fn){
return this.then(null,fn);
}
resolve
//resolve方法
static resolve = (val) => {
return new Promise((resolve, reject) => {
resolve(val);
});
};
reject
//reject方法
static reject = (val) => {
return new Promise((resolve, reject) => {
reject(val);
});
};
race
//race方法
static race = (promises) => {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
};
all
static all = (promises)=>{
let arr = [];
let i = 0;
function processData(index,data){
arr[index] = data;
i++;
if(i == promises.length){
resolve(arr);
};
};
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(data=>{
processData(i,data);
},reject);
};
});
}
完整代码
const PENDING = 'pending'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败
class MyPromise {
// 生成器
constructor(executor) {
// executor 立即执行
// 成功执行 resolve或reject
try {
executor(this.resolve, this.reject);
} catch (e) {
//失败执行reject
this.reject(e);
}
}
status = PENDING;
value = undefined;
reason = undefined;
// 成功回调
successCallback = [];
// 失败回调
failCallback = [];
resolve = (value) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为成功
this.status = FULFILLED;
// 保存成功之后的值
this.value = value;
// 判断成功回调是否存在 如果存在 调用
while (this.successCallback.length) {
this.successCallback.shift()();
}
};
reject = (reason) => {
// 如果状态不是等待 阻止程序向下执行
if (this.status !== PENDING) return;
// 将状态更改为失败
this.status = REJECTED;
// 保存失败后的原因
this.reason = reason;
// 判断成功回调是否存在 如果存在 调用
while (this.failCallback.length) {
this.failCallback.shift()();
}
};
then(successCallback, failCallback) {
// successCallback如果不是函数,就忽略successCallback,直接返回value
successCallback = successCallback ? successCallback : (value) => value;
// failCallback如果不是函数,就忽略failCallback,直接扔出错误
failCallback = failCallback
? failCallback
: (reason) => {
throw reason;
};
let promise2 = new MyPromise((resolve, reject) => {
// 同步情况下成功时执行成功回调
if (this.status === FULFILLED) {
// 回调的函数是否异步
setTimeout(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
// 同步情况下失败时执行失败回调
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
let x = failCallback(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
//异步情况下执行
} else {
// onFulfilled传入到成功数组
this.successCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
// onRejected传入到失败数组
this.failCallback.push(() => {
setTimeout(() => {
try {
let x = successCallback(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
}, 0);
});
}
});
return promise2;
}
catch(fn) {
return this.then(null, fn);
}
//resolve方法
static resolve = (val) => {
return new Promise((resolve, reject) => {
resolve(val);
});
};
//reject方法
static reject = (val) => {
return new Promise((resolve, reject) => {
reject(val);
});
};
//race方法
static race = (promises) => {
return new Promise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
};
static all = (promises)=>{
let arr = [];
let i = 0;
function processData(index,data){
arr[index] = data;
i++;
if(i == promises.length){
resolve(arr);
};
};
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(data=>{
processData(i,data);
},reject);
};
});
}
}
function resolvePromise(promsie2, x, resolve, reject) {
if (promsie2 === x) {
return reject(new TypeError('Chaining cycle detected for promis'));
}
if (x instanceof MyPromise) {
// promise 对象
x.then(
(value) => resolve(value),
(reason) => reject(reason)
);
} else {
// 普通值
resolve(x);
}
}