目录
1. 通过创建一个Promise对象,初始化一个Promise类
1. 通过创建一个Promise对象,初始化一个Promise类
const P = new Promise((resolve,reject) => {
//这里面的代码会立即执行,在PromiseA+规范中叫做excutor,里面提供了resolve和reject两个方法
//在promise内部通常会执行一个异步操作,操作的结果有成功(fulfilled)和失败(rejected)
resolve();//将pending 状态改变为 fulfilled
reject();//将pending 状态改变为 rejected
})
初始化Promise类:
class Promise{
constructor(excutor){
this.state = 'pending'; //初始化这个Promise的状态
this.value = undefined; //初始化这个Promise成功时需要返回的值
this.reason = undefined; //初始化这个Promise失败时返回的值
//在执行resolve的时候将状态从pending改变为fulfilled,并记录调用resolve时传入的值
let resolve = (val) => {
//这里的val是指在调用resolve时传入的值
this.state = 'fulfilled' //改变这个Promise的状态
this.value = val //更新这个Promise的值
}
//reject同上
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
}
try{
excutor(resolve,reject) //立即执行
}catch(err){
reject(err)//执行excutor报错的时候也要返回reject
}
}
}
初始化完成之后尝试调用一下新建的这个Promise类
const P = new Promise((resolve,reject) => {
resolve(200);
reject(500);
})
console.log(P);
得到的结果为:
可以看到我们的resolve和reject都被调用了,因为reason和value都有值,但是state被覆盖了,众所周知,在一个标准的Promise中,是存在 “状态凝固” 的,也就是说,pending要么通过resolve变成fulfilled,要么通过reject变成rejected。不能这样被后面调用的给覆盖了状态,因此我们需要在更改状态的代码片段中加一点限制。
2.状态的限制
let resolve = (val) => {
//只有当状态是pending时才能改变和更新值
if(this.state === 'pending'){
this.state = 'fulfilled'
this.value = val
}
}
//reject同上
let reject = (reason) => {
if(this.state === 'pending'){
this.state = 'rejected'
this.reason = reason
}
}
这样就完成了对状态的限制,接下来就是对.then方法的调用。在PromiseA+规范中,.then方法是写在promise的原型上的,而且.then方法可以传入两个参数,第一个是成功后的回调,第二个是失败后的回调。
const P = new Promise((resolve,reject) => {
resolve(200) //返回成功的状态,更新这个promise对象值为200
})
//当回调是成功时,走第一个箭头函数,并将200赋值给res
//当回调是失败时,走第二个箭头函数,将失败信息赋值给err
P.then(res => {},err => {})
3. ‘.then’的写法:
class Promise{
//以下为原型部分
constructor(excutor){
//以下是实例部分
...
}
/*then:调用Promise对象
@params:
onFulFilled:成功时的回调
onRejected:失败时的回调
@return:
Promise对象的值
*/
then(onFulFilled,onRejected){
//判断Promise对象的状态
if(this.state === 'fulfilled'){
onFulFilled(this.value) //将resolve的值传给res
}
if(this.state === 'rejected'){
onRejected(this.reason) //将reject的值传给err
}
}
}
const P = new Promise(resolve => {
resolve(200)
})
const P2 = new Promise((resolve,reject) => {
reject(500)
})
P.then(res => {
console.log(res) //=>200
})
P2.then(res => {},err =>{
console.log(err) //=>500
})
此时的.then已经完成的差不多了,还剩下最后一个判断,异步处理,在上面的代码中,如果我们在new Promise对象的时候,往Promise内部添加了异步处理,那么.then方法就会先走,然后再回来判断这个Promise对象的状态:
const P = new Promise(resolve => {
setTimeout(() => { //设置异步定时器
resolve(200)
},2000)
})
P.then(res => {
console.log(res);//这里本应该输出200,但是并没有输出
})
console.log(P);
打印p的结果为:
这会导致我们的.then方法不能顺利完成自己应该做的事情。
4. 异步处理
因此我们需要将.then方法中的两个回调(onFulFilled 和 onRejected)设置成,当状态改变时在执行回调函数。所以我们需要在excutor中初始化两个数组用来接受不同状态的回调函数,并且从.then中传那些回调过来
class Promise{
constructor(excutor){
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolveCallBack = []; //存放是成功回调函数的数组
this.onRejectCallBack = []; //存放是失败回调函数的数组
let resolve = (val) => {
this.state = 'fulfilled'
this.value = val
//当执行到resolve的时候,状态改变完成,执行onResolveCallBack里存放的成功回调函数
this.onResolveCallBack.forEach(fn => fn())
}
let reject = (reason) => {
this.state = 'rejected'
this.reason = reason
//reject同上
this.onRejectCallBack.forEach(fn => fn())
}
try{
excutor(resolve,reject)
}catch(err){
reject(err)
}
}
then(onFulFilled,onRejected){
if(this.state === 'fulfilled'){
onFulFilled(this.value)
}
if(this.state === 'rejected'){
onRejected(this.reason)
}
if(this.state === 'pending'){
this.onResolveCallBack.push(()=>{ //向onResolveCallBack中存入成功的回调函数
onFulFilled(this.value)
})
this.onRejectCallBack.push(() => {
onRejected(this.reason) //向onRejectCallBack中存入失败的回调函数
})
}
}
}
验证一下能不能实现异步处理效果:
const P = new Promise((resolve, reject) => {
setTimeout(() => {
resolve(200)
}, 3000);
})
P.then(res => {
console.log(res); //=>200
console.log(P); //=>state:fulfilled;value:200
})

至此,成功实现了Promise.then的异步操作
5.实现链式调用
实现了.then的异步操作之后就是链式调用的问题了,按照现在的 代码,我们无法做到在.then后再次执行.then的操作,如:
const P = new Promise((resolve,reject) => {
resolve(200)
})
P.then(res => {
console.log(res)
return 201
}).then(res => {
console.log(res) //此处应该输出201,但是目前这里并不会进行输出
})
因为.then的操作并没有返回一个Promise对象,因此无法在执行链式调用操作,我们必须让.then的结果是一个Promise对象,并且不能返回本身(P)
class Promise{
...
}
then(onFulFilled,onRejected){
//let promise2 用来接受需要返回的promise对象
let promise2 = new Promise((resolve,reject) => {
if(this.state === 'fulfilled'){
//let x 接收onFulFilled的返回值
let x = onFulFilled(this.value)
}
if(this.state === 'rejected'){
//let y 接收onRejected的返回值
let y = onRejected(this.reason)
}
if(this.state === 'pending'){
this.onResolveCallBack.push(()=>{
onFulFilled(this.value)
})
this.onRejectCallBack.push(() => {
onRejected(this.reason)
})
}
})
return promise2
}
}
此外,我们需要对onFulFilled和onRejected的返回值进行判断
class Promise{
...
}
then(onFulFilled,onRejected){
//let promise2 用来接受需要返回的promise对象
let promise2 = new Promise((resolve,reject) => {
if(this.state === 'fulfilled'){
//这里的代码是与let promise2同步进行,因此需要加上异步操作避免无法获取到promise2
setTimeout(()=>{
//let x 接收onFulFilled的返回值
let x = onFulFilled(this.value)
resolvePromise(promise2,x,resolve,reject) //判断x的返回值
},0)
}
if(this.state === 'rejected'){
//同上
...
}
if(this.state === 'pending'){...}
})
return promise2
}
}
/*
resolvePromise(promise2,x,resolve,reject)判断.then的返回值
@params:
promise2:调用.then函数的对象本身
x:.then的返回值
resolve、reject:处理方法
@return:
根据.then的返回值返回不同的处理结果
1).then的返回值是本身,控制台报错
2).then的返回值是Promise对象,根据Promise对象的状态调用resolve或者reject
3)返回是普通值,直接调用resolve
*/
function resolvePromise(promise2,x,resolve,reject){
//判断.then的返回值是否等于本身
if(x === promise2){
console.err(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
//判断x是否属于Promise对象,如果是,根据其状态来返回结果,如果不是,直接调用resolve
if(x instanceof Promise){
/*x.then((value)=>{
resolve(value)
},err => {
reject(err)
})*/
//上面的片段可以简写为:
x.then(resolve,reject)
}else{
resolve(x)
}
}
//reject的函数处理同上
function rejectPromise(promise2,y,resolve,reject){...}
至此,一个较为完整的Promise对象就写好了
代码完全版:
class Promise {
constructor(excutor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onResolveCallBack = [];
this.onRejectCallBack = [];
let resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled'
this.value = value
this.onResolveCallBack.forEach(fn => fn())
}
}
let reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected'
this.reason = reason
this.onRejectCallBack.forEach(fn => fn())
}
}
try {
excutor(resolve, reject)
} catch (err) {
reject(err)
}
}
then(onFulFilled, onRejected) {
let promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
let x = onFulFilled(this.value)
resolvePromise(promise2, x, resolve, reject)
}, 0);
}
if (this.state === 'rejected') {
setTimeout(() => {
let y = onRejected(this.reason)
rejectPromise(promise2, y, resolve, reject)
}, 0);
}
if (this.state === 'pending') {
this.onResolveCallBack.push(() => {
onFulFilled(this.value)
})
this.onRejectCallBack.push(() => {
onRejected(this.reason)
})
}
})
return promise2
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (x === promise2) {
console.err(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof Promise) {
x.then(resolve, reject)
} else {
resolve(x)
}
}
function rejectPromise(promise2, y, resolve, reject) {
if (y === promise2) {
console.err(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (y instanceof Promise) {
y.then(resolve, reject)
} else {
reject(y)
}
}
测试:
const P = new Promise((resolve, reject) => {
resolve(200);
reject(404);
})
P.then(res => {
console.log(res);
return 500
}).then(res => {
console.log(res);
})
结果为:
链式调用没问题。
163



被折叠的 条评论
为什么被折叠?



