Promise是异步编程的⼀种解决⽅案。编程
Promise对象有如下两个特色:数组
// 建立一个promise对象
var promise = new Promise(function(resolve, reject) {
...
if(/*异步操做成功*/){
resolve(data);
}else {
reject(err)
}
)
复制代码
Promise构造函数接受⼀个函数做为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由JavaScript引擎提供,不⽤⾃⼰部署。promise
Promise实例⽣成之后,能够⽤then⽅法分别指定Resolved状态和Rejected状态的回调函数。bash
promise.then(function(value) {
// success
}, function(err){
// failure
})
复制代码
then ⽅法能够接受两个回调函数做为参数。成功回调和失败回调,其中,第⼆个函数是可选的,不⼀定要提供。这两个函数都接受Promise对象传出的值做为参数。异步
须要注意的是:异步编程
从Promise的使用来看能够分为两部分:新建实例和调用实例的then方法。 因此咱们也能够针对这两部分分别实现:函数
首先从构造函数出发,根据上文对Promise的描述,咱们来实现这个Promise构造函数。ui
Promise构造函数接受⼀个函数做为参数,该函数的两个参数分别是resolve和reject。他们的做用是将state从Pending变为fulfilled或者rejectedthis
function Promise (executor) {
this.state = 'pending';
this.data = undefined;
this.reason= undefined;
this.fn1Callbacks=[];
this.fn2Callbacks=[];
let resolve = value => {
if(this.state === 'pending'){
this.state = 'fulfilled';
this.data = value;
for(let i = 0; i<this.fn1Callbacks.length; i++){
self.fn1Callbacks[i](value);
}
}
};
let reject = reason => {
if(this.state === 'pending'){
this.state = 'rejected';
this.reason = reason;
for (let i = 0; i < self.fn2Callback.length; i++) {
self.fn2Callback[i](reason);
}
}
};
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
复制代码
当Promise的状态发生了改变,不管是成功或是失败都会调用then方法。spa
Promise实例具备then方法,即then方法是定义在原型对象Promise.prototype上的。它的做用是为Promise实例添加状态改变时的回调函数并在异步完成时执行这个函数。
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。所以能够采用链式写法,即then方法后面再调用另外一个then方法。
基于上面的讨论咱们很容易得出结论:
下面咱们来看看promise实现
// then方法接收两个参数,fn1,fn2,分别为Promise成功或失败后的回调
Promise.prototype.then = function(fn1, fn2) {
var self = this
var promise2
// 首先对入参 fn1, fn2作判断
fn1 = typeof fn1 === 'function' ? fn1 : function(v) {}
fn2 = typeof fn2 === 'function' ? fn2 : function(r) {}
if (self.status === 'resolved') {
return promise2 = new Promise(function(resolve, reject) {
//todo
})
}
if (self.status === 'rejected') {
return promise2 = new Promise(function(resolve, reject) {
//todo
})
}
if (self.status === 'pending') {
return promise2 = new Promise(function(resolve, reject) {
// todo
})
}
}
复制代码
首先是对输入的成功回调和失败回调进行类型判断,明确是个函数再执行它,接下来是处理Promise中可能存在的有三种可能的状态,咱们分三个if块来处理,在里面分别都返回一个new Promise。
因此,接下来的逻辑是:
根据上面的逻辑,填充下面代码:
Promise.prototype.then = function(fn1, fn2) {
var self = this
var promise2
fn1 = typeof fn1 === 'function' ? fn1 : function(v) {}
fn2 = typeof fn2 === 'function' ? fn2 : function(r) {}
if (self.status === 'resolved') {
return promise2 = new Promise(function(resolve, reject) {
// 把 fn一、fn2 放在 try catch 里面,毕竟 fn一、fn2 是用户传入的,报错嘛,很常见
try {
var x = fn1(self.data)
// fn1 执行后,会有返回值,经过 resolve 注入到 then 返回的 promise 中
resolve(x)
} catch (e) {
reject(e)
}
})
}
if (self.status === 'rejected') {
return promise2 = new Promise(function(resolve, reject) {
try {
var x = fn2(self.data)
reject(x)
} catch (e) {
reject(e)
}
})
}
if (self.status === 'pending') {
return promise2 = new Promise(function(resolve, reject) {
this.fn1Callback.push(function(value){
try {
var x = fn1(self.data);
resolve(x)
} catch (e) {
reject(e)
}
})
this.fn2Callback.push(function(value) {
try {
var x = fn2(self.data);
reject(x)
} catch (e) {
reject(e)
}
})
})
}
}
复制代码