深入理解ES6 Promise:从原理到实战的八步解析
本文通过八段代码深入解析ES6 Promise的核心机制。内容涵盖Promise的立即执行特性、三种状态(Pending、Resolved、Rejected)及其不可逆性、链式调用的返回值处理规则、then回调的异步执行顺序,以及Promise.resolve与reject在拆箱行为上的关键差异,帮助开发者彻底掌握异步编程的最佳实践。
ES6 Promise核心机制解析
前言
ES6标准引入了Promise概念,旨在优化回调函数的使用体验,解决深层嵌套导致的代码可读性差和结构混乱问题。JavaScript社区推崇链式调用风格,Promise正是为此而生。本文将通过八个具体代码示例,系统性地解析Promise的工作机制,帮助读者全面掌握这一核心特性。
Promise的立即执行特性
1. Promise的立即执行特性
var p = new Promise(function(resolve, reject){
console.log("create a promise");
resolve("success");
});
console.log("after new Promise");
p.then(function(value){
console.log(value);
});
控制台输出:
"create a promise"
"after new Promise"
"success"
Promise实例在创建(new)时,其构造函数内的回调函数会立即同步执行,无论内部逻辑是同步还是异步。常见误区是认为只有调用then方法时回调才会执行,这是错误的。因此,代码中create a promise的输出顺序先于after new Promise。
Promise的三种状态
2. Promise的三种状态
var p1 = new Promise(function(resolve,reject){
resolve(1);
});
var p2 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(2);
}, 500);
});
var p3 = new Promise(function(resolve,reject){
setTimeout(function(){
reject(3);
}, 500);
});
console.log(p1);
console.log(p2);
console.log(p3);
setTimeout(function(){
console.log(p2);
}, 1000);
setTimeout(function(){
console.log(p3);
}, 1000);
p1.then(function(value){
console.log(value);
});
p2.then(function(value){
console.log(value);
});
p3.catch(function(err){
console.log(err);
});
控制台输出:
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
1
2
3
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}
Promise内部实现为状态机,包含三种状态:pending(进行中)、resolved(已成功)和rejected(已失败)。初始创建时处于pending状态;若执行resolve,则转为resolved;若执行reject,则转为rejected。
p2和p3刚创建时均为pending状态,但p1为何直接显示为resolved?因为p1的构造函数内执行的是同步代码,resolve在创建瞬间即被调用,故后续输出显示其状态为resolved。通过setTimeout延迟1秒后,p2和p3已完成执行,状态分别变为resolved和rejected。
Promise状态的不可逆性
3. Promise状态的不可逆性
var p1 = new Promise(function(resolve, reject){
resolve("success1");
resolve("success2");
});
var p2 = new Promise(function(resolve, reject){
resolve("success");
reject("reject");
});
p1.then(function(value){
console.log(value);
});
p2.then(function(value){
console.log(value);
});
控制台输出:
"success1"
"success"
一旦Promise状态变为resolved或rejected,其状态和值即固定,后续再调用resolve或reject均无效。因此,p1中resolve("success2")无法将值修改为success2,p2中reject("reject")也无法将状态由resolved改为rejected。
链式调用机制
4. 链式调用机制
var p = new Promise(function(resolve, reject){
resolve(1);
});
p.then(function(value){ //第一个then
console.log(value);
return value*2;
}).then(function(value){ //第二个then
console.log(value);
}).then(function(value){ //第三个then
console.log(value);
return Promise.resolve('resolve');
}).then(function(value){ //第四个then
console.log(value);
return Promise.reject('reject');
}).then(function(value){ //第五个then
console.log('resolve: '+ value);
}, function(err){
console.log('reject: ' + err);
})
控制台输出:
1
2
undefined
"resolve"
"reject: reject"
Promise的then方法返回一个新的Promise实例,支持链式调用。then接收两个回调:成功回调和失败回调,二者仅有一个会被触发,其返回值决定新Promise的状态和值。返回值可能为以下三种情况之一:
- 返回同步值或undefined(无有效返回值时默认为undefined),then返回resolved状态的Promise,值为该返回值。
- 返回另一个Promise,then根据该Promise的状态和值创建并返回新的Promise。
- 抛出同步异常,then返回rejected状态的Promise,值为该异常。
基于上述规则,第一个then返回值为2(1*2)、状态为resolved的Promise,故第二个then输出2。第二个then无返回值,返回默认undefined,第三个then输出undefined。第三个then返回resolved状态的Promise,第四个then返回rejected状态的Promise,分别由第四个then的成功回调和第五个then的失败回调处理。
then回调的异步性
5. Promise then() 回调的异步性
var p = new Promise(function(resolve, reject){
resolve("success");
});
p.then(function(value){
console.log(value);
});
console.log("which one is called first ?");
控制台输出:
"which one is called first ?"
"success"
Promise构造函数内的回调是同步执行的,但then中的回调函数是异步执行的。因此,"success"会在后续输出。
Promise中的异常处理
6. Promise中的异常处理
var p1 = new Promise( function(resolve,reject){
foo.bar();
resolve( 1 );
});
p1.then(
function(value){
console.log('p1 then value: ' + value);
},
function(err){
console.log('p1 then err: ' + err);
}
).then(
function(value){
console.log('p1 then then value: '+value);
},
function(err){
console.log('p1 then then err: ' + err);
}
);
var p2 = new Promise(function(resolve,reject){
resolve( 2 );
});
p2.then(
function(value){
console.log('p2 then value: ' + value);
foo.bar();
},
function(err){
console.log('p2 then err: ' + err);
}
).then(
function(value){
console.log('p2 then then value: ' + value);
},
function(err){
console.log('p2 then then err: ' + err);
return 1;
}
).then(
function(value){
console.log('p2 then then then value: ' + value);
},
function(err){
console.log('p2 then then then err: ' + err);
}
);
控制台输出:
p1 then err: ReferenceError: foo is not defined
p2 then value: 2
p1 then then value: undefined
p2 then then err: ReferenceError: foo is not defined
p2 then then then value: 1
Promise中的异常由then的第二个回调(失败回调)处理,异常信息作为Promise的值。异常处理后,后续Promise恢复正常,由成功回调处理。需注意,p1和p2的多级then回调交替执行,这源于then回调的异步特性。
Promise.resolve()方法
7. Promise.resolve()方法
var p1 = Promise.resolve( 1 );
var p2 = Promise.resolve( p1 );
var p3 = new Promise(function(resolve, reject){
resolve(1);
});
var p4 = new Promise(function(resolve, reject){
resolve(p1);
});
console.log(p1 === p2);
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);
p4.then(function(value){
console.log('p4=' + value);
});
p2.then(function(value){
console.log('p2=' + value);
})
p1.then(function(value){
console.log('p1=' + value);
})
控制台输出:
true
false
false
false
p2=1
p1=1
p4=1
Promise.resolve(...)可接收普通值或Promise对象。若为普通值,返回resolved状态的Promise,值为该参数;若为Promise对象,直接返回该对象,故p1 === p2。但通过new创建的Promise均为新对象,后续比较结果为false。p4的then最先调用却最后输出,是因为其resolve参数为Promise对象p1,resolve会对p1进行“拆箱”获取状态和值,该过程是异步的,详见下一节。
resolve与reject的差异
8. resolve与reject的差异
var p1 = new Promise(function(resolve, reject){
resolve(Promise.resolve('resolve'));
});
var p2 = new Promise(function(resolve, reject){
resolve(Promise.reject('reject'));
});
var p3 = new Promise(function(resolve, reject){
reject(Promise.resolve('resolve'));
});
p1.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
p2.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
p3.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
控制台输出:
p3 rejected: [object Promise]
p1 fulfilled: resolve
p2 rejected: reject
Promise回调中的resolve参数具备“拆箱”能力:若参数为Promise对象,resolve会异步获取其状态和值。p1拆箱后状态为resolved,触发fulfilled回调;p2拆箱后状态为rejected,触发rejected回调。而reject参数不具备拆箱能力,其参数直接传递给then的失败回调。因此,即使p3的reject接收了resolved状态的Promise,then仍调用rejected回调,且参数为reject接收到的Promise对象。
总结
本文全面解析了ES6 Promise的核心机制,涵盖状态管理、链式调用、异步处理及关键方法差异。希望这些内容能协助读者深入理解并应用Promise,提升JavaScript异步编程能力。如有疑问,欢迎留言交流,感谢支持。
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
