实现一个promise
emmm,前面那篇 blog讲的东西都比较深入了,不管我们在使用一个东西或者方法的时候自然是要知其然更要知其所以然,所以今天打算来谈谈我们究竟应该如何去实现一个promise呢?
一、Promise的A+规范
首先,我们需要了解设计一个Promise所需要遵循的规范守则是什么,这时候就要提及ES6中实现promise所使用的A+规范了。
要求
promise 的状态 ----
1. 等待态(pending)
此状态可以迁移至执行态或拒绝态
2. 执行态(fulfilled)
不能迁移至其他的任何状态
必须拥有一个不可变的终值(理解这里的终值的概念)
3. 拒绝态(rejected)
不能迁移至其他的任何状态
必须拥有一个不可变的拒因(理解这里的拒因的概念)
then方法
一个Promise必须要提供一个then方法来访问当前值、终值和拒因。then方法注册了 两个回调函数(onFulfilled 、onRejected)分别来表示成功与失败的执行方法,且then方法返回的也必须是一个promise对象
至此,你应该是可以实现这样一个promise方法了
function myPromise(constuctor) {
var self = this //不进行替换则下面函数中的this不是内部this,而是global对象
self.status = 'pending'//初始化状态
self.value = undefined //value 为resolve的值
self.reason = undefined // reason 为reject的值,初始化时均为undefined
// 成功的回调
function resolve(value) {
if (self.status === 'pending') {
self.value = value
self.status = 'resolved'
}
}
// 失败的回调
function reject(value) {
if (self.status === 'pending') {
self.value = value
self.status = 'rejected'
}
}
//捕获异常
try {
constuctor(resolve, reject)
} catch (e) {
reject(e)
}
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
var self = this
switch (self.status) {
case 'resolved':
onFulfilled(self.value)
break
case 'rejected':
onRejected(self.reason)
break
}
}
有没有发现有什么问题呢?
是的,按规范里说,这个 then 方法应该返回的是一个promise对象啊,不然我怎么实现链式调用呢,别急慢慢来。。。
先想一个问题
Promise链式操作中,执行顺序是如何保证的
每个promise后面链一个对象该对象包含onfulfiled,onrejected,子promise三个属性,
当父promise 状态改变完毕,执行完相应的onfulfiled/onfulfiled的时候呢,
拿到子promise,在等待这个子promise状态改变,再执行相应的onfulfiled/onfulfiled。
依次循环直到当前promise没有子promise
仔细研究,我们需要做的便是使then方法的调用返回一个promise对象,就可以实现链式操作了。于是乎,我们写出了这样的代码
function myPromise(constuctor) {
var self = this //不进行替换则下面函数中的this不是内部this,而是global对象
self.status = 'pending'//初始化状态
self.value = undefined //value 为resolve的值
self.reason = undefined // reason 为reject的值,初始化时均为undefined
// 解决无法处理异步resolve方法的问题
self.onFulfilledArray=[];// 存储fulfilled状态对应的onFulfilled函数
self.onRejectedArray=[];
// 成功的回调
function resolve(value) {
if (self.status === 'pending') {
self.value = value
self.status = 'resolved'
self.onFulfilledArray.forEach(f => {
f(self.value)
//如果状态从pending变为resolved,
//那么就遍历执行里面的异步方法
})
}
}
// 失败的回调
function reject(resolve) {
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
self.onRejectedArray.forEach(function(f){
f(self.reason)
//如果状态从pending变为rejected,
//那么就遍历执行里面的异步方法
})
}
}
//捕获异常
try {
constuctor(resolve, reject)
} catch (e) {
reject(e)
}
}
myPromise.prototype.then = function (onFulfilled, onRejected) {
var self = this
var promise2
// 根据标准,如果then的参数不是function,则我们需要忽略它,此处以如下方式处理
// onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function(value) {}
// onRejected = typeof onRejected === 'function' ? onRejected : function(reason) {}
switch (self.status) {
case "pending":
// 等待状态添加相关执行函数
// 保证.then返回的也是一个promise对象
promise2 = new myPromise(function(resolve, reject){
self.onFulfilledArray.push(function(){
try{
var temp = onFulfilled(self.value)
resolve(temp)
}catch(e){
reject(e)
}
})
self.onRejectedArray.push(function(){
try{
var temp = onRejected(self.value)
reject(temp)
}catch(e){
reject(e)
}
})
})
break//之前忘记加这个,找了快两个小时的bug出在哪里,自闭。。。
case "resolved":
promise2 = new myPromise(function(resolve, reject){
try{
var temp = onFulfilled(self.value)
resolve(temp)
}catch(e){
reject(e)
}
})
break
case "rejected":
promise2 = new myPromise(function(resolve, reject){
try{
var temp = onRejected(self.value)
reject(temp)
}catch(e){
reject(e)
}
})
break
}
return promise2
}
好的,到这里你对promise的整个运行过程相信也熟悉的差不多了,但是这个promise好像始终不是很完美呀!还记得之前也说过就是在Promise/A+规范中then函数里面的onFullfilled方法和onRejected方法的返回值可以是对象,函数,甚至是另一个promise。
这个又该如何处理呢?
你是否还有尝试过promise.all 和promise.race这些个api呢,不要急,留待下回分解。。。