function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
function resolve(value){
if( self.status === 'pending'){
self.status = 'fulfilled';
self.value = value;
}
}
function reject(reason){
if( self.status === 'pending'){
self.status = 'rejected';
self.reason = reason;
}
}
executor(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
if(self.status === 'fulfilled'){
onFulfilled(self.value);
}
if(self.status === 'rejected'){
onRejected(self.reason);
}
}
module.exports = Promise;
复制代码
测试用例1数组
let Promise = require('Mypromise');
let promise = newPromise(function(resolve,reject){
resolve(results)
})
promise.then(function(data){
console.log(data);
},function(err){
console.log(err);
})
复制代码
首先咱们定义一个status状态变量,默认Promise处于pending状态
promise
promise接收一个executor函数,该函数在构造promise实例时就执行,因此在Promise构造方法中执行executor,executor须要接收resolve做为执行成功时的回调函数,接收reject做为执行失败时的回调函数,因此定义了resolve和reject方法
bash
resolve接收执行成功的返回结果做为参数
reject 接收执行失败的返回结果做为参数
因此这里定义了value表示成功结果,reason表示错误缘由
调用resolve或reject后,会让promise进入filfilled成功状态或rejected失败状态,而且只有promise为在pending状态下,才能切换到成功/失败态
异步
promise实例须要用then方法注册执行成功/失败的回调方法,then中根据promise所处状态,判断调用成功仍是失败的回调
这样一个简单的promise的实现就写好了函数
function Promise(executor){
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.onResolvedCallbacks = [];
self.onRejectedCallbacks = [];
function resolve(value){
if( self.status === 'pending'){
self.status = 'fulfilled';
self.value = value;
self.onResolvedCallbacks.forEach(function(fn){
fn();
})
}
}
function reject(reason){
if( self.status === 'pending'){//只能从pending状态切换到rejected状态
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function(fn){
fn();
})
}
}
executor(resolve,reject);
}
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
if(self.status === 'fulfilled'){
onFulfilled(self.value);
}
if(self.status === 'rejected'){
onRejected(self.reason);
}
if(self.status === 'pending'){
self.onResolvedCallbacks.push( function(){
onFulfilled(self.value)
});
self.onRejectedCallbacks.push( function(){
onRejected(self.reason)
});
}
}
module.exports = Promise;
复制代码
测试用例2post
let promise = new Promise(function(resolve,reject){
http.get(url, function(results) {
resolve(results)
})
})
promise.then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
promise.then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
promise.then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
复制代码
promise主要用于处理异步回调的状况,上例中发起http请求,请求成功后,用resolve发起成功的回调;并调用屡次then注册了多个成功、失败的回调方法;若是执行成功,原生的promise会将每一个then的成功回调都执行一遍
测试
因为异步的请求,当调用then时,promise还处于pending状态,因此咱们须要将then注册的回调方法暂存,以便成功或失败时回调,为此定义 onResolvedCallbacks 、onRejectedCallbacks 分别存放then注册的成功、失败回调方法,上例所示, 可能屡次调用then注册,因此onResolvedCallbacks =[],是个数组
当执行成功会调用resolve,那咱们在实现resolve方法时,将全部then中的成功回调都调用一遍,就是这段代码ui
self.onResolvedCallbacks.forEach(function(fn){
fn();
})
复制代码
当执行异步操做时有可能发生异常,须要try/catch捕获到异常,并使promise进入rejected状态this
try {
executor(resolve,reject); //捕获的时候发生异常,执行reject
} catch (error) {
reject(error)
}
复制代码
能够在executor中抛出throw new Error('error')测试
url
then中不管是执行成功的回调仍是失败回调,只要有返回结果,都会走到下一个then(根据不一样返回结果进入下一个then的不一样回调,规则个人另外一偏文章juejin.im/post/5aae65…
promise是经过then中返回新的promise来实现链式调用的,试想:一个新的promise是能够继续调用then方法的,补充then方法以下
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
let promise2; //then返回的新Promise
if(self.status === 'fulfilled'){
//onFilfilled会同步执行,并返回新的promise2
promise2 = new Promise(function (resolve,reject) {
onFulfilled(self.value);
});
}
if(self.status === 'rejected'){
promise2 = new Promise(function (resolve,reject) {
onRejected(self.reason);
});
}
if(self.status === 'pending'){
promise2 = new Promise(function (resolve,reject) {
self.onResolvedCallbacks.push( function(){
//捕获异步回调时的异常,若是有进入promise2的失败态
try{
onFulfilled(self.value);
}catch (e){
reject(e);
}
});
self.onRejectedCallbacks.push( function(){
try{
onRejected(self.reason);
}catch (e){
reject(e);
}
});
});
}
return promise2;
}
复制代码
上面代码第一个if语句,执行成功回调时,返回新的promise2,由于new promise时,executor会当即执行,因此onFulfilled(成功回调)方法会同步执行,并捕获其中的异常;第二个if语句失败回调同理。
第三个if语句,若是是异步回调,执行promise2的executor方法时,只是将这个成功的回调onFulfilled加入成功回调队列onResolvedCallbacks(失败同理),当成功回调真正执行时,若是发生异常,还须要捕获,并进入新promise2的失败态
若是第一个promise返回一个普通值,会走到下一次then的成功的回调
若是第一个promise返回了一个promise,须要等待返回的promise执行后的结果,再传递给下一次then中。
因此咱们用x接收第一个then的返回值 let x = onFulfilled(self.value);
x多是普通值,也多是promise,也多是别人实现的promise, 这里实现一个resolvePromise方法统一处理返回值
then的代码更新以下 : 都用x接收回调函数的返回值,并调用resolvePromise来处理
Promise.prototype.then = function(onFulfilled,onRejected){
let self = this;
let promise2;//then返回的新Promise
if(self.status === 'fulfilled'){
promise2 = new Promise(function (resolve,reject) {
let x= onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
});
}
if(self.status === 'rejected'){
promise2 = new Promise(function (resolve,reject) {
let x= onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
});
}
if(self.status === 'pending'){
promise2 = new Promise(function (resolve,reject) {
self.onResolvedCallbacks.push( function(){
try{
let x= onFulfilled(self.value);
resolvePromise(promise2,x,resolve,reject);
}catch (e){
reject(e);
}
});
self.onRejectedCallbacks.push( function(){
try{
let x= onRejected(self.reason);
resolvePromise(promise2,x,resolve,reject);
}catch (e){
reject(e);
}
});
});
}
return promise2;
}
复制代码
resolvePromise的实现以下
参数:
p2 :第二次then的promise实例
x:第一次then的返回值
resolve/reject : p2的 resolve/reject
function resolvePromise(p2,x,resolve,reject){
if(p2 === x){ //报一个类型错误
return reject(new TypeError('循环引用了'));
}
//判断x是否是promise
if(x!== null || (typeof x === 'object'||typeof x === 'function')){
//x多是promise 看对象中是否有then方法,有then就认为是promise
//取then方法有可能异常,发生异常就进入p2的失败态
try {
let then = x.then;
if(typeof then === 'function'){
//认为x是一个promise,马上执行该promise的then方法
//若是x进入成功态,会触发成功回调
then.call(x,function(y){
//y可能仍是一个promise,继续解析,直到返回的是一个普通值
resolvePromise(p2,y,resolve,reject);
},function(err){ //若是x进入失败态,会触发p2的失败态
reject(err);
});
}else{ //若是then不是方法,直接认为返回一个对象,调用p2成功态
resolve(x);
}
} catch (error) {
reject(error);
}
}else{ //x是普通值,调用p2成功态
resolve(x);
}
};
复制代码
若是有人把代码写成
let p1= new Promise(function (resolve,reject) {
resolve('success');
reject('fail1');
});
复制代码
promise的处理方式是,一旦进入成功态,就成功了,不会再调用reject,反之亦然
这里经过在resolvePromise方法中,加入called 标识,表示已经进入一个resolve或reject;若果called为true,直接返回,若是为false,置为true
function resolvePromise(p2, x, resolve, reject) {
if (p2 === x) { //这里应该报一个类型错误,有问题
return reject(new TypeError('循环引用了'))
}
let called; // 表示是否调用过成功或者失败
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, function (y) {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject)
}, function (err) { //失败
if (called) return;
called = true;
reject(err);
})
} else {
resolve(x)
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else { // 说明是一个普通值1
resolve(x); // 表示成功了
}
}
复制代码
咱们能够在then中什么都不写
p1.then().then().then(function(data){
console.log('data',data);
},function(err){
console.log('err',err);
})
复制代码
p1的执行结果依然会穿透到最后一个then的相应的回调
这须要在then方法中一开始就判断,是否有resolve/reject方法,若是没有,须要给默认的处理方法
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled :
function(value){ //默认的成功回调,返回一个值,就会进入下一个then的成功回调
return value;
};
onRejected = typeof onRejected === 'function' ? onRejected :
function(err){//默认的失败回调,抛出异常,就会进入下一个then的失败回调
throw err;
};
复制代码
捕获错误的方法,catch就至关于一个then调用错误方法
Promise.prototype.catch = function (callback) {
return this.then(null,callback);
}
复制代码
all接收一个成员为promise实例的数组,依次执行,并按顺序返回执行结果
当全部promise都执行成功,就进入成功态,有一个执行失败了,就进入失败态
//promises是一个promise的数组
Promise.all = function (promises) {
return new Promise(function (resolve, reject) {
let arr = []; //arr是最终返回值的结果
let count = 0; // 表示成功了多少次
function processData(index, y) {
arr[index] = y;
if (++count === promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (y) {
processData(i, y)
}, reject) //有一个失败,就调用失败回调
}
})
};
复制代码
参数同all,只要有一个promise成功了,就算成功。若是有一个失败了,就失败了,其余promise继续执行
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve,reject)
}
})
};
复制代码
Promise.resolve 能够理解为 生成一个成功的promise
Promise.resolve = function(value){
return new Promise(function(resolve,reject){
resolve(value);
})
}
复制代码
Promise.reject 即生成一个失败的promise
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
})
}
复制代码
这里用setTimeout模拟异步执行,将全部成功和失败的回调都用setTimeout包装,既然异步执行,还需捕获异常
function Promise(executor) { // executor是一个执行函数
let self = this;
self.status = 'pending';
self.value = undefined; // 默认成功的值
self.reason = undefined; // 默认失败的缘由
self.onResolvedCallbacks = []; // 存放then成功的回调
self.onRejectedCallbacks = []; // 存放then失败的回调
function resolve(value) { // 成功状态
if (self.status === 'pending') {
self.status = 'resolved';
self.value = value;
self.onResolvedCallbacks.forEach(function (fn) {
fn();
});
}
}
function reject(reason) { // 失败状态
if (self.status === 'pending') {
self.status = 'rejected';
self.reason = reason;
self.onRejectedCallbacks.forEach(function (fn) {
fn();
})
}
}
try {
executor(resolve, reject)
} catch (e) { // 捕获的时候发生异常,就直接失败了
reject(e);
}
}
function resolvePromise(promise2, x, resolve, reject) {
// 有可能这里返回的x是别人的promise
// 尽量容许其余乱写
if (promise2 === x) { //这里应该报一个类型错误,有问题
return reject(new TypeError('循环引用了'))
}
// 看x是否是一个promise,promise应该是一个对象
let called; // 表示是否调用过成功或者失败
if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
// 多是promise {},看这个对象中是否有then方法,若是有then我就认为他是promise了
try { // {then:1}
let then = x.then;
if (typeof then === 'function') {
// 成功
then.call(x, function (y) {
if (called) return
called = true
// y可能仍是一个promise,在去解析直到返回的是一个普通值
resolvePromise(promise2, y, resolve, reject)
}, function (err) { //失败
if (called) return
called = true
reject(err);
})
} else {
resolve(x)
}
} catch (e) {
if (called) return
called = true;
reject(e);
}
} else { // 说明是一个普通值1
resolve(x); // 表示成功了
}
}
Promise.prototype.then = function (onFulfilled, onRjected) {
//成功和失败默认不穿给一个函数
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : function (value) {
return value;
}
onRjected = typeof onRjected === 'function' ? onRjected : function (err) {
throw err;
}
let self = this;
let promise2; //返回的promise
if (self.status === 'resolved') {
promise2 = new Promise(function (resolve, reject) {
// 当成功或者失败执行时有异常那么返回的promise应该处于失败状态
// x多是一个promise 也有多是一个普通的值
setTimeout(function () {
try {
let x = onFulfilled(self.value);
// x多是别人promise,写一个方法统一处理
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
}
if (self.status === 'rejected') {
promise2 = new Promise(function (resolve, reject) {
setTimeout(function () {
try {
let x = onRjected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
})
}
// 当调用then时可能没成功 也没失败
if (self.status === 'pending') {
promise2 = new Promise(function (resolve, reject) {
// 此时没有resolve 也没有reject
self.onResolvedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onFulfilled(self.value);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e)
}
})
});
self.onRejectedCallbacks.push(function () {
setTimeout(function () {
try {
let x = onRjected(self.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (e) {
reject(e);
}
})
});
})
}
return promise2;
}
// 捕获错误的方法
Promise.prototype.catch = function (callback) {
return this.then(null, callback)
}
// 解析所有方法
Promise.all = function (promises) {
//promises是一个promise的数组
return new Promise(function (resolve, reject) {
let arr = []; //arr是最终返回值的结果
let i = 0; // 表示成功了多少次
function processData(index, y) {
arr[index] = y;
if (++i === promises.length) {
resolve(arr);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(function (y) {
processData(i, y)
}, reject)
}
})
};
// 只要有一个promise成功了 就算成功。若是第一个失败了就失败了
Promise.race = function (promises) {
return new Promise(function (resolve, reject) {
for (var i = 0; i < promises.length; i++) {
promises[i].then(resolve,reject)
}
})
}
// 生成一个成功的promise
Promise.resolve = function(value){
return new Promise(function(resolve,reject){
resolve(value);
})
}
// 生成一个失败的promise
Promise.reject = function(reason){
return new Promise(function(resolve,reject){
reject(reason);
})
}
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise(function (resolve, reject) {
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd
}
module.exports = Promise;
复制代码