开发过程异步请求很常见,但是回调地狱我们还是可以去避免的,这篇文章就不再赘述Promise的具体使用方法,而是探寻一下它的实现机制。首先是一个简单的Promise的例子:
function getInfo(){
return new Promise(function(reslve,reject){
http.get(url,function(result){
reslove(reslut.id)
})
})
}
getInfo().then(function(id){...})
开始的时候最大的疑惑是:.then()的操作怎么就知道我的异步请求成功了?其实内部的原理就是在一个promise的实例里面的then方法注册我所有异步请求成功后的回调,而后通过reslove方法将异步请求结果返回,也就是将之前注册的异步回调一一执行,大概的实现代码就是:
function Promise(fn){
var value = null
var callbacks = [] //异步回调的数组
this.then(function(callbackDone){
callbacks.push(callbackDone) // 将所有的异步回调放入数组
return this //支持链式调用
})
function reslove(value){
callbacks.forEach(function(callback){
callback(value) // 遍历执行异步回调
})
}
fn(reslove)
}
描述起来就是我们在new Promise()的时候,传入的函数执行异步请求,将异步请求的回调通过调用.then()方法将回调注册入callbacks里,异步请求成功之后执行reslove(result)的方法,将异步回调全部执行。这就是一个Promise最基础版本的实现,那目前的问题就是不能让reslove的方法先于then方法执行,那我们能想到最简单的方法就是加入定时器的延时处理:
function Promise(fn){
var value = null
var callbacks = [] //异步回调的数组
this.then(function(callbackDone){
callbacks.push(callbackDone) // 将所有的异步回调放入数组
return this //支持链式调用
})
setTimeout(function(){
// 延时处理
function reslove(value){
callbacks.forEach(function(callback){
callback(value) // 遍历执行异步回调
})
}
},0)
fn(reslove)
而接下来就是考虑状态机制的问题了,我们都知道Promise的三个状态:pending,fulfilled,rejected。而且只能是由pending变为fulfilled或rejected且状态不可逆,也就是状态一旦改变就不会再次改变了,那我们将代码稍微改动下:
function Promise(fn){
var value = null
var callbacks = [] //异步回调的数组
var status = 'pending'
this.then(function(callbackDone){
if(status === 'pending'){
callbacks.push(callbackDone) // 将所有的异步回调放入数组
}
callbackDone(value)
return this //支持链式调用
})
setTimeout(function(){
// 延时处理
function reslove(newValue){
var value = newValue
status = 'fulfilled'
callbacks.forEach(function(callback){
callback(value) // 遍历执行异步回调
})
}
},0)
fn(reslove)
其实以上就是Promise实现的核心代码,后续还会涉及到异常处理和链式Promise,我也需要更进一步的学习,不过目前也是已经了解到Promise内部实现的机制是怎样的,也很有助于我平常使用的时候更好的理解它。那后期会再更一版Promise的实现机制(二),对于异常处理和链式Promise再进行一些探讨