参考文献
new Promise传的参数我们称之为执行器函数(executor),在创建实例的实例会立即执行,看代码
console.log(1);
new Promise((resolve,reject)=>{
console.log(2);
})
console.log(3); //打印结果1,2,3.说明你在new时候,我们称之为执行器函数就立即执行了
实现promise状态

- 代码如下
class Promise{
constructor(executor){
//默认状态 等待态
this.status = 'pending';
// 成功的结果
this.value = undefined;
//失败的原因
this.reason = undefined;
// 成功态执行函数
let fulfilled = (value)=>{
//防止状态改变
if(this.status ==='pending'){
this.status ==='resolved' //成功态
// 成功的结果
this.value = value;
}
};
//失败态执行函数
let rejected = (reason)=>{
//防止状态改变
if(this.status ==='pending'){
this.status ==='rejected' //失败态
// 失败原因
this.reason = reason;
}
};
// 默认让执行器执行,可能会发生错误
try{
executor(fulfilled,rejected);
}catch (e) {
rejected(e)
}
}
}
module.exports = Promise;
then方法的实现
步骤一、实现同步promise(每个步骤配一个例子来看效果)
class Promise{
constructor(executor){
//默认状态 等待态
this.status = 'pending';
// 成功的结果
this.value = undefined;
//失败的原因
this.reason = undefined;
// 成功态执行函数
let fulfilled = (value)=>{
if(this.status ==='pending'){
this.status ='resolved' //成功态
// 成功的结果
this.value = value;
}
};
//失败态执行函数
let rejected = (reason)=>{
if(this.status ==='pending'){
this.status ='rejected' //失败态
// 失败原因
this.reason = reason;
}
};
// 默认让执行器执行,可能会发生错误
try{
executor(fulfilled,rejected);
}catch (e) {
rejected(e)
}
}
then(onFulfilled, onRejected) {
if(this.status ==="resolved"){
onFulfilled(this.value)
}
if(this.status ==="rejected"){
onRejected(this.reason)
}
}
}
module.exports = Promise;
那就来简单测试下

步骤二、有可能我们会往执行器中写一些异步逻辑,这个时候我们该怎么做呢?
了解过发布订阅模式应该知道。我们应该先把回调函数存放数组中,等发布时候在让数组中函数一一调用。修改下代码
class Promise{
constructor(executor){
//默认状态 等待态
this.status = 'pending';
// 成功的结果
this.value = undefined;
//失败的原因
this.reason = undefined;
// 成功存放的数组
this.onResolvedCallbacks = [];
// 失败存放的数组
this.onRejectedCallbacks = [];
// 成功态执行函数
let fulfilled = (value)=>{
if(this.status ==='pending'){
this.status ='resolved' //成功态
// 成功的结果
this.value = value;
//依次执行成功的回调函数
this.onResolvedCallbacks.forEach(fn=>fn())
}
};
//失败态执行函数
let rejected = (reason)=>{
if(this.status ==='pending'){
this.status ='rejected' //失败态
// 失败原因
this.reason = reason;
//依次执行失败的回调函数
this.onRejectedCallbacks.forEach(fn=>fn())
}
};
// 默认让执行器执行,可能会发生错误
try{
executor(fulfilled,rejected);
}catch (e) {
rejected(e)
}
}
then(onFulfilled, onRejected) {
if(this.status ==="resolved"){
onFulfilled(this.value)
}
if(this.status ==="rejected"){
onRejected(this.reason)
}
//如果等待态(即异步逻辑时)要做一件事情
if(this.status ==='pending'){
this.onResolvedCallbacks.push(()=>{
onFulfilled(this.value);
})
this.onRejectedCallbacks.push(()=>{
onRejected(this.reason);
})
}
}
}
module.exports = Promise;
测试写代码

步骤三、实现穿透,看下原生promise就秒懂什么是穿透啦
let p = new Promise((resolve,reject)=>{ //引用原生的promise
resolve("买")
});
p.then().then().then().then(data=>{ //可以无限的.then,最终拿到data值。即穿透
console.log(data);
});
怎么实现的呢,先看下promiseA+规范中定义,然后我们用代码实现它


- then返回新的promise2
then(onFulfilled, onRejected) {
let promise2;
//默认成功和失败不穿参数情况
onFulfilled = typeof onFulfilled ==="function"? onFulfilled:value=>value;
onRejected = typeof onRejected ==="function"? onRejected:err=>{
throw err;
};
promise2 = new Promise((resolve,reject)=>{
if(this.status ==="resolved"){
//成功逻辑
let x = onFulfilled(this.value);
/* 判断x是不是promise,如果是promise取它结果,作为promise2成功结果
*要是返回普通值,作为promise2成功的结果
* todo: resolvePromise可以解析x和promise2关系
*/
resolvePromise(promise2,x,resolve,reject);
}
if(this.status ==="rejected"){
//失败逻辑
let x= onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}
//如果等待态(即异步逻辑时)要做一件事情
if(this.status ==='pending'){
this.onResolvedCallbacks.push(()=>{
let x = onFulfilled(this.value);
resolvePromise(promise2,x,resolve,reject);
})
this.onRejectedCallbacks.push(()=>{
let x = onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
})
}
})
//调用then后,返回新的promise2。实现多次then
return promise2;
}
- 解析x和promise2的关系。定义方法 resolvePromise()

// //解析x与promise2的关系
function resolvePromise(promise2,x,resolve,reject) {
/*判断x是不是promise
*A+规范规定一段代码,这个代码可以实现我们的promise和别人的promise可以进行交互
*/
if (promise2 === x) { //自己不能等待自己完成
return reject(new TypeError('循环引用'));
}
// x不是null或者是对象或者函数
if(x!==null && typeof x === 'object' || typeof x==='function'){
let called; //标识promise是否被调用过,防止成功后调用失败
try{ //防止取then出现异常
let then = x.then; // 取x的then方法
if(typeof then === 'function'){ //如果then是函数我就认为它是promise
then.call(x,y=>{ //call第一个参数是this,后面是成功和失败的回调
if(called) return
called = true;
// 如果y是promise就继续递归解析promise
resolvePromise(promise2,y,resolve,reject);
},err=>{ //只要失败就失败
if(called) return
called = true;
reject(err);
});
}else {
//then是一个普通对象
if(called) return
called = true;
resolve(x)
}
}catch (e) {
reject(e)
}
}else {
resolve(x);
}
}
这样基本的promise就算实现完成了
步骤五优化一些细节,包括try catch的捕获及异步的处理

- 整理后的then方法就是这样,每句代码都有对应注释,在A+规范可以对应找到
then(onFulfilled, onRejected) {
let promise2;
//默认成功和失败不穿参数情况
onFulfilled = typeof onFulfilled ==="function"? onFulfilled:value=>value;
onRejected = typeof onRejected ==="function"? onRejected:err=>{
throw err;
};
promise2 = new Promise((resolve,reject)=>{
if(this.status ==="resolved"){
//执行上下文为异步
setTimeout(()=>{
try{
//成功逻辑
let x = onFulfilled(this.value);
/* 判断x是不是promise,如果是promise取它结果,作为promise2成功结果
*要是返回普通值,作为promise2成功的结果
* todo: resolvePromise可以解析x和promise2关系
*/
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
}
if(this.status ==="rejected"){
setTimeout(()=>{
try{
//失败逻辑
let x= onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
}
//如果等待态(即异步逻辑时)要做一件事情
if(this.status ==='pending'){
this.onResolvedCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onFulfilled(this.value);
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
});
this.onRejectedCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
})
}
})
//调用then后,返回新的promise2。实现多次then
return promise2;
}
catch用法
- 接受参数只有失败
- 只是then没有成功的简写
catch(onRejected){ //接受参数只有失败
return this.then(null,onRejected)
}
Promise.resolve()
- 基础用法可以看上篇文章,这里就不在解释了,直接写实现原理
- 返回promise,直接调用成功
Promise.resolve = function (val){ //
return new Promise((resolve,reject)=>resolve(val)
)
};
Promise.reject()的实现
- 返回一个promise
- 把值传给成功的回调
Promise.reject = function (val){
return new Promise((resolve,reject)=>reject(val)
)
};
promise.all()实现
接受一个数组,返回一个promise,处理每个参数的返回结果,有一个失败就失败,全部成功才成功
Promise.all = function(promises){ //返回promise,接受一个数组
let arr = [];
let i=0; //i的目的是为了保证获取全部成功,来设置索引
function processDara(index,data){
arr[index] = data;
i++;
if(i ===promises.length){
resolve(arr);
}
}
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(data=>{
//处理数据
processDara(i,data)
},err=>{ //有一个失败就失败
reject(err)
})
}
})
};
Promise.race()实现
接受一个数组,与all不同的是,不用处理数据,有一个成功就成功,有一个失败就失败
Promise.race = function(promises){ //返回promise,接受一个数组
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(data=>{ //有一个成功就成功
resolve(data)
},err=>{ //有一个失败就失败
reject(err)
})
}
})
};
最后放一个测试promise安装包
// 目前是通过他测试 他会测试一个对象
// 语法糖
Promise.defer = Promise.deferred = function () {
let dfd = {}
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
// npm install promises-aplus-tests -g
// promises-aplus-tests 文件名称
测试下我们写的全部代码

附上我们全部代码供大家参考,有不对地方请大家指正
// //解析x与promise2的关系
function resolvePromise(promise2,x,resolve,reject) {
/*判断x是不是promise
*A+规范规定一段代码,这个代码可以实现我们的promise和别人的promise可以进行交互
*/
if (promise2 === x) { //自己不能等待自己完成
return reject(new TypeError('循环引用'));
}
// x不是null或者是对象或者函数
if(x!==null && (typeof x === 'object' || typeof x==='function')){
let called; //标识promise是否被调用过,防止成功后调用失败
try{ //防止取then出现异常
let then = x.then; // 取x的then方法
if(typeof then === 'function'){ //如果then是函数我就认为它是promise
then.call(x,y=>{ //call第一个参数是this,后面是成功和失败的回调
if(called) return;
called = true;
// 如果y是promise就继续递归解析promise
resolvePromise(promise2,y,resolve,reject);
},r=>{ //只要失败就失败
if(called) return
called = true;
reject(r);
});
}else {
resolve(x)
}
}catch (e) {
//then是一个普通对象
if(called) return
called = true;
reject(e)
}
}else {
resolve(x);
}
}
class Promise{
constructor(executor){
//默认状态 等待态
this.status = 'pending';
// 成功的结果
this.value = undefined;
//失败的原因
this.reason = undefined;
// 成功存放的数组
this.onResolvedCallbacks = [];
// 失败存放的数组
this.onRejectedCallbacks = [];
// 成功态执行函数
let fulfilled = (value)=>{
if(this.status ==='pending'){
this.status ='resolved' //成功态
// 成功的结果
this.value = value;
//依次执行成功的回调函数
this.onResolvedCallbacks.forEach(fn=>fn())
}
};
//失败态执行函数
let rejected = (reason)=>{
if(this.status ==='pending'){
this.status ='rejected' //失败态
// 失败原因
this.reason = reason;
//依次执行失败的回调函数
this.onRejectedCallbacks.forEach(fn=>fn())
}
};
// 默认让执行器执行,可能会发生错误
try{
executor(fulfilled,rejected);
}catch (e) {
rejected(e)
}
}
then(onFulfilled, onRejected) {
let promise2;
//默认成功和失败不穿参数情况
onFulfilled = typeof onFulfilled ==="function"? onFulfilled:value=>value;
onRejected = typeof onRejected ==="function"? onRejected:err=>{
throw err;
};
promise2 = new Promise((resolve,reject)=>{
if(this.status ==="resolved"){
//执行上下文为异步
setTimeout(()=>{
try{
//成功逻辑
let x = onFulfilled(this.value);
/* 判断x是不是promise,如果是promise取它结果,作为promise2成功结果
*要是返回普通值,作为promise2成功的结果
* todo: resolvePromise可以解析x和promise2关系
*/
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
}
if(this.status ==="rejected"){
setTimeout(()=>{
try{
//失败逻辑
let x= onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
}
//如果等待态(即异步逻辑时)要做一件事情
if(this.status ==='pending'){
this.onResolvedCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onFulfilled(this.value);
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
});
this.onRejectedCallbacks.push(()=>{
setTimeout(()=>{
try{
let x = onRejected(this.reason);
resolvePromise(promise2,x,resolve,reject);
}catch (e) {
reject(e)
}
})
})
}
})
//调用then后,返回新的promise2。实现多次then
return promise2;
}
catch(onRejected){ //接受参数只有失败
return this.then(null,onRejected)
}
}
module.exports = Promise;
Promise.resolve = function (val){
return new Promise((resolve,reject)=>resolve(val)
)
};
Promise.reject = function (val){
return new Promise((resolve,reject)=>reject(val)
)
};
Promise.all = function(promises){ //返回promise,接受一个数组
let arr = [];
let i=0; //i的目的是为了保证获取全部成功,来设置索引
function processDara(index,data){
arr[index] = data;
i++;
if(i ===promises.length){
resolve(arr);
}
}
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(data=>{
//处理数据
processDara(i,data)
},err=>{ //有一个失败就失败
reject(err)
})
}
})
};
Promise.race = function(promises){ //返回promise,接受一个数组
return new Promise((resolve,reject)=>{
for(let i=0;i<promises.length;i++){
promises[i].then(data=>{ //有一个成功就成功
resolve(data)
},err=>{ //有一个失败就失败
reject(err)
})
}
})
};
// 目前是通过他测试 他会测试一个对象
// 语法糖
Promise.defer = Promise.deferred = function () {
let dfd = {};
dfd.promise = new Promise((resolve,reject)=>{
dfd.resolve = resolve;
dfd.reject = reject;
});
return dfd;
}
module.exports = Promise;
// npm install promises-aplus-tests -g
// promises-aplus-tests 文件名称