实现Promise
第一步:定义构造,接受一个函数作为参数,这个函数有两个参数,这两个参数都是函数,分别是resolve和reject。resolve作用是把状态从pending改变为fulfilled,异步操作成功后,把值传递出去。reject作用是把状态从pending改变为rejected,异步操作失败后,把报错信息传递出去,需要注意的是,它有三种状态,分别是pending(进行中),fulfilled(已成功),rejected(已失败),状态一旦凝固,将不可改变。
const PENDING = 'pending';//进行中
const FULFILLED = 'fulfilled';//成功
const REJECTED = 'rejected';//失败
/*
*promsie构造
*@params executor {funciton} 接收一个函数,为了接受暴漏的resolve和reject
*/
function MyPromise(executor) {
let self = this;
self.status = PENDING;
self.fulfilledValue = undefined;//状态置为fulfilled时候,传递的值
self.rejectValue = undefined;//状态置为rejected时候,传递的值
/*
*成功
*@params value {引用类型|基本类型} 接受状态置为成功,传递的值
*/
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED;
self.fulfilledValue = value;
}
}
/*
*失败
*@params value {引用类型|基本类型} 接受状态置为失败,传递的值
*/
function reject(value) {
if (self.status === PENDING) {
self.status = REJECTED;
self.rejectValue = value;
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
第二步,定义原型上的then方法,then方法提供两个回调函数,一个是成功的回调,一个是失败的回调,这里需要注意,接收的必须是必须是函数。
/*
*then,成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled =typeof onFulfilled === "function"? onFulfilled: function(param) {return param;};
onRejected =typeof onRejected === "function"? onRejected: function(e) {throw e;}
switch (self.status) {
//状态为成功
case FULFILLED:
onFulfilled(self.fulfilledValue);
break;
//状态为失败
case REJECTED:
onRejected(self.rejectValue);
break;
}
}
截至目前,promise的简单框架已经搭好了,咱们现在也测试一下。
var promise=new MyPromise(function(resolve,reject){
resolve("promise")
})
promise.then((data)=>{
console.log(data)//promsie
})
结果表明成功了,但是我们再来看一下例子:
var promise=new MyPromise(function(resolve,reject){
// setTimeout(()=>{
resolve("promise")
// })
})
promise.then((data)=>{
console.log(data)
})
console.log("1111")
看下控制台结果:
哇,promise阻塞了同步任务的执行,这显然违背了promise的初衷,所以,成功和失败的回调应该是异步的。
/*
*then,成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled =typeof onFulfilled === "function"? onFulfilled: function(param) {return param;};
onRejected =typeof onRejected === "function"? onRejected: function(e) {throw e;}
switch (self.status) {
//状态为成功
case FULFILLED:
setTimeout(funciton(){
onFulfilled(self.fulfilledValue);
})
break;
//状态为失败
case REJECTED:
setTimeout(funciton(){
onRejected(self.rejectValue);
})
break;
}
}
好了,这里就成功了解决了阻塞的问题,但是这里还有个问题,相信大家都已经猜出来了,就是resolve是异步的情况下,在调用then的时候,状态还没有置为fulfilled或者rejected,那么这时候是没有可执行的代码,所以呢,我们就需要提供状态为pending时的逻辑,解决方案就是,提供两个数组,分别用来存储成功和失败的回调,等异步队列有结果返回时,就去循环所存的回调。
/*
*promsie构造
*@params executor {funciton} 接收一个函数,为了接受暴漏的resolve和reject
*/
function MyPromise(executor) {
let self = this;
self.status = PENDING;
self.onFullfilledArray = [];//成功的回调数组
self.onRejectedArray = []; //失败的回调数组
self.fulfilledValue = undefined;//状态置为fulfilled时候,传递的值
self.rejectValue = undefined;//状态置为rejected时候,传递的值
/*
*成功
*@params value {引用类型|基本类型} 接受状态置为成功,传递的值
*/
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED;
self.fulfilledValue = value;
for (let fn of self.onFullfilledArray) {
fn()
}
}
}
/*
*失败
*@params value {引用类型|基本类型} 接受状态置为失败,传递的值
*/
function reject(value) {
if (self.status === PENDING) {
self.status = REJECTED;
self.rejectValue = value;
for (let fn of self.onRejectedArray) {
fn()
}
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
/*
*then,成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
let promise2;
switch (self.status) {
//状态为进行中
case PENDING:
self.onFullfilledArray.push(function(){
setTimeout(function(){
onFulfilled(self.fulfilledValue)
})
})
self.onRejectedArray.push(function(){
setTimeout(function(){
onRejected(self.fulfilledValue)
})
})
break;
//状态为成功
case FULFILLED:
setTimeout(function(){
onFulfilled(self.fulfilledValue);
})
break;
//状态为失败
case REJECTED:
setTimeout(function() {
onRejected(self.rejectValue);
})
break;
}
}
好了,截至目前基本的架构算是真正的解决,接下来,咱们就去完成它的精髓,就是实现then的链式调用,所以then必须返回一个崭新的promise。
/*
*then,成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
let promise2;
switch (self.status) {
//状态为进行中
case PENDING:
promise2 = new MyPromise(function (resolve, reject) {
self.onFullfilledArray.push(function () {
setTimeout(function () {
onFulfilled(self.fulfilledValue)
})
})
self.onRejectedArray.push(function () {
setTimeout(function () {
onRejected(self.fulfilledValue)
})
})
})
break;
//状态为成功
case FULFILLED:
promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
onFulfilled(self.fulfilledValue);
})
})
break;
//状态为失败
case REJECTED:
promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
onRejected(self.rejectValue);
})
})
break;
}
return promise2
}
好了,目前已经可以链式调用了,但是,目前是无法进行值的传递的,接下来咱们就来实现值的传值,then的返回值有三种情况
- 如果x为对象或者函数
(1)把x.then赋给then
(2)如果取x.then值的时候抛出错误e,则reject()
(3)如果x不为对象或函数,则resolve(x);
(4)如果x时函数,则以x作为函数作用域this调用之,同样返回成功回调和失败回调,如果成功,则运行[[Resolve]](promise, y) - x为新的promsie实例
如果x为promsie,则使 promsie接受x的状态 - 直接resolve
/*
*成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
/*
*then,成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
let promise2;
switch (self.status) {
//状态为进行中
case PENDING:
promise2 = new MyPromise(function (resolve, reject) {
self.onFullfilledArray.push(function () {
setTimeout(function () {
try{
let results=onFulfilled(self.fulfilledValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
self.onRejectedArray.push(function () {
setTimeout(function () {
try{
let results=onRejected(self.rejectValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
})
break;
//状态为成功
case FULFILLED:
promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
try{
let results=onFulfilled(self.fulfilledValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
break;
//状态为失败
case REJECTED:
promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
try{
let results=onRejected(self.rejectValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
break;
}
return promise2
}
/*
*处理then返回值
*@params promise2 新创建的promise
*@params result then的返回值
*@params resolve 成功
*@params reject 失败
**/
function resolvePromise(promise2, result, resolve, reject) {
if (promise2 === result) { //不支持then()将自己创建的Promise进行返回
return new TypeError("Chaining cycle")
} else if (result instanceof MyPromise) {
// 如果 result 为 Promise ,则使 promise 接受 result 的状态
// 如果 result 处于等待态, promise 需保持为等待态直至 result 被执行或拒绝
if (result.status === PENDING) {
result.then(
y => {
resolvePromise(promise2, y, resolve, reject)
},
reason => {
reject(reason)
}
)
} else {
// 如果 result 处于执行态,用相同的值执行 promise
// 如果 result 处于拒绝态,用相同的据因拒绝 promise
result.then(resolve, reject)
}
} else if (result && (typeof result === "object" || typeof result === "function")) {
let isUsed=false;
let then=result.then;
if (typeof then === "function") {
then.call(result,function(data){
resolvePromise(promise2,data,resolve,reject)
},function(e){
reject(e)
})
}else{
resolve(result)
}
} else {
resolve(result)
}
}
OK,接下来我们来测试一下,先测试下不是数组也不是对象的。
var promise=new MyPromise(function(resolve,reject){
setTimeout(()=>{
resolve("promise")
})
})
promise.then((data)=>{
console.log(data)
return "不是对象也不是数组"
}).then((data)=>{
console.log(data);
return function add(){
console.log("函数")
}
}).then((data)=>{
console.log(data)
})
完美!!完全正确,接下来测试下thenable的。
var promise=new MyPromise(function(resolve,reject){
setTimeout(()=>{
resolve("promise")
})
})
promise.then((data)=>{
console.log(data)
return {
then:function(resolve,reject){
resolve("thenable")
}
}
}).then((data)=>{
console.log(data)
})
nice!!!也正确,接下在测试一下返回值为promsie的
var promise=new MyPromise(function(resolve,reject){
setTimeout(()=>{
resolve("promise")
})
})
promise.then((data)=>{
console.log(data);
return new MyPromise((resolve,reject)=>{
resolve("返回Promise")
})
}).then((data)=>{
console.log(data)
})
大功告成!!!!!
全部源码
es5写法:
!function(win){
const PENDING = 'pending';//进行中
const FULFILLED = 'fulfilled';//成功
const REJECTED = 'rejected';//失败
/*
*promsie构造
*@params executor {funciton} 接收一个函数,为了接受暴漏的resolve和reject
*/
function MyPromise(executor) {
let self = this;
self.status = PENDING;
self.onFullfilledArray = [];//成功的回调数组
self.onRejectedArray = []; //失败的回调数组
self.fulfilledValue = undefined;//状态置为fulfilled时候,传递的值
self.rejectValue = undefined;//状态置为rejected时候,传递的值
/*
*成功
*@params value {引用类型|基本类型} 接受状态置为成功,传递的值
*/
function resolve(value) {
if (self.status === PENDING) {
self.status = FULFILLED;
self.fulfilledValue = value;
for (let fn of self.onFullfilledArray) {
fn()
}
}
}
/*
*失败
*@params value {引用类型|基本类型} 接受状态置为失败,传递的值
*/
function reject(value) {
if (self.status === PENDING) {
self.status = REJECTED;
self.rejectValue = value;
for (let fn of self.onRejectedArray) {
fn()
}
}
}
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
/*
*成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
/*
*then,成功或失败的回调
*@params onFulfilled 成功的回调
*@params onRejected 失败的回调
*/
MyPromise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
let promise2;
switch (self.status) {
//状态为进行中
case PENDING:
promise2 = new MyPromise(function (resolve, reject) {
self.onFullfilledArray.push(function () {
setTimeout(function () {
try{
let results=onFulfilled(self.fulfilledValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
self.onRejectedArray.push(function () {
setTimeout(function () {
try{
let results=onRejected(self.rejectValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
})
break;
//状态为成功
case FULFILLED:
promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
try{
let results=onFulfilled(self.fulfilledValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
break;
//状态为失败
case REJECTED:
promise2 = new MyPromise(function (resolve, reject) {
setTimeout(function () {
try{
let results=onRejected(self.rejectValue);
resolvePromise(promise2,results,resolve,reject)
}catch(e){
reject(e)
}
})
})
break;
}
return promise2
}
/*
*处理then返回值
*@params promise2 新创建的promise
*@params result then的返回值
*@params resolve 成功
*@params reject 失败
**/
function resolvePromise(promise2, result, resolve, reject) {
if (promise2 === result) { //不支持then()将自己创建的Promise进行返回
return new TypeError("Chaining cycle")
} else if (result instanceof MyPromise) {
// 如果 result 为 Promise ,则使 promise 接受 result 的状态
// 如果 result 处于等待态, promise 需保持为等待态直至 result 被执行或拒绝
if (result.status === PENDING) {
result.then(y => {
resolvePromise(promise2, y, resolve, reject)
},reason => {
reject(reason)
})
} else {
// 如果 result 处于执行态,用相同的值执行 promise
// 如果 result 处于拒绝态,用相同的据因拒绝 promise
result.then(resolve, reject)
}
} else if (result && (typeof result === "object" || typeof result === "function")) {
let isUsed=false;
let then=result.then;
if (typeof then === "function") {
then.call(result,function(data){
resolvePromise(promise2,data,resolve,reject)
},function(e){
reject(e)
})
}else{
resolve(result)
}
} else {
resolve(result)
}
}
win.MyPromise=MyPromise
}(window)
es6写法
(function(win){
const PENDING = 'pending' // 进行中
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected'// 失败
let thenValue;
/*
* reslove
*/
const resolve = function(value){
if(this.promiseStatus===PENDING){
this.promiseStatus = FULFILLED
this.fulfilledValue = value
for(let fn of this.fulfilledArr){
fn(this.fulfilledValue)
}
}
}
/*
* reject
*/
const reject = function(value){
if(this.promiseStatus===PENDING){
this.promiseStatus = REJECTED
this.rejectedValue = value
for(let fn of this.rejectedArr){
fn(this.rejectedValue)
}
}
}
/*
* then的返回值处理
* des {
* 1.对象或者函数
* 2.新的promsie实例
* 3.无返回值
* }
*/
const delFn = function(promise2,result,resolve,reject){
if(promise2 === result){
throw new TypeError ('Chaining cycle')
} else if (result instanceof myPromise){
if(result.status === PENDING) {
result.then((y)=>{
delFn(promise2,y,resolve,reject)
},(reson)=>{
reject(reason)
})
}
} else if(result && (typeof result === "object" || typeof result === "function")){
let thenCalledOrThrow = false
let then = result.then
if (typeof then === 'function'){
then.call(result,function(data){
if (thenCalledOrThrow) return
thenCalledOrThrow = true
delFn(promise2,data,resolve,reject)
},function(e){
if (thenCalledOrThrow) return
thenCalledOrThrow = true
reject(e)
})
} else {
if (thenCalledOrThrow) return
thenCalledOrThrow = true
resolve(result)
}
} else {
if (thenCalledOrThrow) return
thenCalledOrThrow = true
resolve(result)
}
}
class myPromise {
constructor(executor){
this.promiseStatus = PENDING
this.fulfilledValue = ''
this.rejectedValue = ''
this.fulfilledArr = [] // 成功回调,因为reslove可能会存在异步,所以需要存起来
this.rejectedArr = [] // 失败回调,因为reject可能也会存在异步,所以需要存起来
try {
executor(resolve.bind(this), reject.bind(this))
} catch (e) {
reject.call(this,e);
}
}
then(resloveFun,rejectFun){
let promise2
resloveFun = typeof resloveFun === "function" ? resloveFun : function (param) { return param; };
rejectFun = typeof rejectFun === "function" ? rejectFun : function (e) { throw e; }
switch (this.promiseStatus) {
case PENDING:
promise2 = new myPromise ((resolve,reject)=>{
this.fulfilledArr.push(()=>{
setTimeout(()=>{
try {
thenValue = resloveFun(this.fulfilledValue)
delFn(promise2,thenValue,resolve,reject)
} catch (error) {
reject(error)
}
})
})
this.rejectedArr.push(()=>{
setTimeout(()=>{
try {
thenValue = rejectFun(this.rejectedValue)
delFn(promise2,thenValue,resolve,reject)
} catch (error) {
reject(error)
}
})
})
})
break
case FULFILLED :
promise2 = new myPromise ((resolve,reject)=>{
setTimeout(()=>{
try {
thenValue = resloveFun(this.fulfilledValue)
delFn(promise2,thenValue,resolve,reject)
} catch (error) {
reject(error)
}
},0)
})
break
case REJECTED :
promise2 = new myPromise ((resolve,reject)=>{
setTimeout(()=>{
try {
thenValue = rejectFun(this.rejectedValue)
delFn(promise2,thenValue,resolve,reject)
} catch (error) {
reject(error)
}
},0)
})
break
}
return promise2
}
catch(reject){
return this.then(null,reject)
}
finally(cb){
return this.then((val)=>{
myPromise.reslove(cb()).then(()=>{
return val
})
},(err)=>{
myPromise.reslove(cb()).then(()=>{
throw err
})
})
}
static reslove (pro) {
let promise
promise = new myPromise((reslove, reject)=>{
delFn(promise, pro, reslove, reject)
})
return promise
}
static all(proArr){
let allPro = null
let arr = []
allPro = new myPromise((reslove,reject)=>{
for(let i=0;i<proArr.length;i++){
myPromise.reslove(proArr[i]).then((data)=>{
arr[i] = proArr[i].fulfilledValue
if(arr.length === proArr.length){
reslove(arr)
}
},(err)=>{
reject(err)
})
}
})
return allPro
}
static reject(value) {
let promise;
promise = new myPromise((resolve, reject)=>{
reject(value)
})
return promise
}
static race(arr) {
return new myPromise((resolve, reject)=>{
arr.forEach(item => {
item.then((data)=>{
resolve(data)
},function(err){
reject(err)
})
});
})
}
}
win.myPromise = myPromise
})(window)