前面打好了基础,现在就开始手写promise。我们定义一个Promise函数。
定义一个二维数组,用于记录异步操作的信息。包括信息,状态等。
定义返回的对象chain,定义全局的state状态
protect 是绑定状态,成功和失败的回调才可以改变,所以不能直接绑定到返回的对象chain上。
let tuples = [
["resolve",'done',container('once memory'),'resolved'],
["reject",'fail',container('once memory'),'rejected'],
]
let state = 'pending'
let chain = {} //promise返回的是一个对象
let protect = {}
我们遍历这个数组,去获取container这个函数容器,得到的是两个外形一样的对象,但是其实他们是完全不一样的两个功能,一个是处理成功的,一个是处理失败的。
tuple【2】 其实就是这个容器。
tuples.forEach((tuple,i)=>{
let list = tuple[2]
console.log(list)
})
我们通过tuple【3】 去获取回调执行的状态。这里下标写死是没问题的,因为这个二维数组是我们定义的。
如果有状态,不管是成功还是失败,我们都往容器里去添加一个回调。在这个回调里我们可以进行状态的改变。
同时给返回的chain对象上添加一些方法,比如then等。
list.add 就是一个语法糖,我们通过done或者fail的调用,去向容器中添加成功或者失败的回调函数,
tuples.forEach((tuple,i)=>{
let list = tuple[2]
let stateString = tuple[3]
if(stateString){
list.add(function(){
state = stateString
})
}
chain[tuple[1]] = list.add
})
我们还要给返回的对象上去绑定状态。因为我们知道promise的状态确定以后就无法改变。而且只有异步操作的结果可以改变这个状态。所以在函数内部定义一个对象去绑定状态(就是上面定义的protect)
tuples.forEach((tuple,i)=>{
let list = tuple[2]
let stateString = tuple[3]
if(stateString){
list.add(function(){
state = stateString
})
}
chain[tuple[1]] = list.add
protect[tuple[0]] = function(){
protect[tuple[0]+'Bind'](this,arguments)
}
protect[tuple[0]+'Bind'] = list.startBind
})
整体的一个雏形就出来了:
function Promise(func){
let tuples = [
["resolve",'done',container('once memory'),'resolved'],
["reject",'fail',container('once memory'),'rejected'],
]
let state = 'pending'
let protect = {}
let chain = {} //promise返回的是一个对象
tuples.forEach((tuple,i)=>{
let list = tuple[2]
let stateString = tuple[3]
if(stateString){
list.add(function(){
state = stateString
})
}
chain[tuple[1]] = list.add
protect[tuple[0]] = function(){
protect[tuple[0]+'Bind'](this,arguments)
}
protect[tuple[0]+'Bind'] = list.startBind
})
if(func){
func.call(chain,protect['resolve'],protect['reject'])
}
return chain
}