Promise、 Async和Await详解
一、初识Promise
先演示一个常见的异步编程误区 —— 在 setTimeout 回调中返回值无法被外层函数捕获。代码如下:
function fn(counter) {
setTimeout(() => {
if (counter > 0) {
let total = 0;
for (let i = 0; i <= counter; i++) {
total += i;
}
return total // ❗这个 return 只作用于箭头函数内部
} else {
return "你传递的数据不合法~"
}
}, 3000)
}
console.log(fn(100))
运行结果如下:

显示是undifined。
我们再改造一下代码,在代码中添加“return "ok"”,代码如下:
function fn(counter) {
setTimeout(() => {
if (counter > 0) {
let total = 0;
for (let i = 0; i <= counter; i++) {
total += i;
}
return total // ❗这个 return 只作用于箭头函数内部
} else {
return "你传递的数据不合法~"
}
}, 3000)
return "ok" // ✅ 这是 fn 函数实际返回的值
}
console.log(fn(100))
运行结果如下:

输出结果为OK。这是为什么呢?
🔍 关键问题解析:
1. setTimeout 是异步的
2. 回调中的 return 无效
- ***************************************************************************************************
- ✅ 如果希望这段代码真正“工作”,改用 Promise 模式!
-
function fn(counter) { return new Promise((resolve, reject) => { setTimeout(() => { if (counter > 0) { let total = 0; for (let i = 0; i <= counter; i++) { total += i; } resolve(total); } else { reject("你传递的数据不合法~"); } }, 3000); }); } // 调用方式: fn(100).then(result => console.log(result), err => console.log(err));运行结果如下:
![image]()
- 或者,promise模式的另一种写法,代码如下:
-
function fn(counter) { let p = new Promise((resolve, reject) => { setTimeout(() => { if (counter > 0) { let total = 0; for (let i = 0; i <= counter; i++) { total += i; } resolve(total); } else { reject("你传递的数据不合法~"); } }, 3000); }); return p; } // 调用方式: fn(100).then(result => console.log(result)).catch(err => console.log(err));运行结果如下:
![image]()
- 二、resolve的实参问题
-
resolve是 Promise 构造函数中执行器(executor)的第一个参数,它是一个函数,调用时传入的实参会决定当前 Promise 的最终状态和后续.then()回调的入参。下面从基础到进阶,详细说明 resolve 实参的不同情况:1. 基础情况:传入普通值(非 Promise/thenable)
如果 resolve 的实参是普通值(数字、字符串、对象、null、undefined 等),Promise 会立即进入fulfilled(已完成)状态,这个值会作为后续.then()第一个回调函数的参数。示例代码: -
// 传入普通字符串 const p1 = new Promise((resolve) => { resolve("成功的结果"); // resolve 实参为普通字符串 }); p1.then((result) => { console.log(result); // 输出:成功的结果 }); // 传入普通对象 const p2 = new Promise((resolve) => { resolve({ code: 200, data: [1, 2, 3] }); // resolve 实参为对象 }); p2.then((res) => { console.log(res.data); // 输出:[1, 2, 3] });运行结果如下:
![image]()
-
2. 特殊情况 1:传入另一个 Promise 实例
如果 resolve 的实参是另一个 Promise 实例,当前 Promise 会 “接管” 这个实例的状态:- 若传入的 Promise 已完成,当前 Promise 也完成,取其结果;
- 若传入的 Promise 已拒绝,当前 Promise 也拒绝,取其错误;
- 若传入的 Promise 未决(pending),当前 Promise 会等待其状态确定。
示例代码: -
// 先定义一个待完成的 Promise const p3 = new Promise((resolve) => { setTimeout(() => resolve("p3 的结果"), 1000); }); // resolve 传入 p3(Promise 实例) const p4 = new Promise((resolve) => { resolve(p3); // 实参是另一个 Promise }); p4.then((result) => { console.log(result); // 1秒后输出:p3 的结果 }); // 传入已拒绝的 Promise const p5 = Promise.reject("出错了"); const p6 = new Promise((resolve) => { resolve(p5); }); p6.catch((err) => { console.log(err); // 输出:出错了 });运行结果如下:
![image]()
-
3. 特殊情况 2:传入 thenable 对象(有 .then () 方法的对象)
如果 resolve 的实参是具有 .then () 方法的对象 / 函数(称为 thenable),Promise 会自动执行这个.then()方法,并传入自己的 resolve 和 reject 作为参数,相当于 “同化” 这个 thenable 的行为。示例代码: -
// 定义一个 thenable 对象 const thenableObj = { then: function (resolve, reject) { setTimeout(() => resolve("thenable 的结果"), 1500); }, }; const p7 = new Promise((resolve) => { resolve(thenableObj); // 实参是 thenable 对象 }); p7.then((result) => { console.log(result); // 1.5秒后输出:thenable 的结果 });再学习一个.then()方法的示例,这是ES6 方法简写模式,代码如下:
-
let promise = new Promise((resolve,reject)=>{ resolve( {then(resolve,reject){ resolve("this is thenable!") }} ); }); promise.then((value)=>{ console.log("value is:",value); }) - 对象字面量(最常用)与ES6方法简写模式是等价的,结果是一样的,如下所示
-
let promise = new Promise((resolve, reject) => { resolve({ then: function(resolve, reject) { // 这里是对象的属性 key: value resolve("this is thenable!"); } }); }); promise.then((value) => { console.log("value is:", value); // 输出: value is: this is thenable! }); -
运行结果如下:
![image]()
- 更改一下上述代码,具体如下:
-
let promise = new Promise((resolve,reject)=>{ resolve( function then(resolve,reject){ resolve("this is thenable!") } ); }); promise.then((value)=>{ console.log("value is:",value); }) - 输出的结果却是
![image]()
-
详细分析
1. 为什么逻辑失效了?
Promise 的resolve函数在处理传入值时,遵循以下规则:









浙公网安备 33010602011771号