Promise 是 ES6 引入的异步编程解决方案,本质是一个表示异步操作最终完成或失败的对象。它有三种状态:
- pending(进行中):初始状态,尚未完成或失败
- fulfilled(已完成):异步操作成功完成
- rejected(已拒绝):异步操作失败

一、Promise 构造函数
-
语法 :new Promise((resolve, reject) => { /* 异步操作 */ })
-
参数
-
resolve
:是一个函数,当异步操作成功完成时调用,它接收一个参数,该参数会成为 Promise 解决(fulfilled)状态下.then()
回调函数的参数。 -
reject
:也是一个函数,当异步操作失败时调用,它接收一个参数,通常是一个错误对象,该对象会成为 Promise 拒绝(rejected)状态下.catch()
回调函数的参数。// 修改为函数形式,每次调用返回一个新的 Promise
const getRandomNumber = () => {
return new Promise((resolve, reject) => {
const random = Math.random();
if (random > 0.5) {
resolve(random);
} else {
reject(new Error('随机数小于0.5'));
}
});
};// 第一次调用
getRandomNumber()
.then(result => console.log('第一次结果:', result))
.catch(error => console.log('第一次失败:', error));// 第二次调用
getRandomNumber()
.then(result => console.log('第二次结果:', result))
.catch(error => console.log('第二次失败:', error));
-
-
函数形式 :将
getRandomNumber
定义为函数,每次调用getRandomNumber()
会创建一个新的 Promise,确保两次调用独立执行。 -
处理成功和失败 :每个调用都通过
.then()
处理成功结果,通过.catch()
处理错误,确保无论随机数是否大于 0.5,都能看到输出。
二、Promise 中 resolve 和 reject 的源码解析与工作原理
在 JavaScript 引擎中,Promise
构造函数里的resolve
和reject
是其内部实现的核心部分,它们主要用于控制Promise
对象状态的转变。虽然 JavaScript 引擎的底层实现是用 C++ 等语言编写,无法直接查看源码,但可以通过模拟实现来理解其工作原理和参数传入后的执行逻辑。
Promise
对象通常包含状态属性、用于存储成功结果或失败原因的属性,以及存放then
方法中回调函数的队列。以下是一个简化的Promise
模拟实现:
function MyPromise(executor) {
// 初始状态为pending
this.status = 'pending';
// 成功的值,初始为null
this.value = null;
// 失败的原因,初始为null
this.reason = null;
// 成功回调函数队列
this.onFulfilledCallbacks = [];
// 失败回调函数队列
this.onRejectedCallbacks = [];
// 定义resolve函数
const resolve = (val) => {
if (this.status === 'pending') {
this.status = 'fulfilled';
this.value = val;
// 依次执行成功回调函数队列中的函数
this.onFulfilledCallbacks.forEach(callback => callback(this.value));
}
};
// 定义reject函数
const reject = (err) => {
if (this.status === 'pending') {
this.status ='rejected';
this.reason = err;
// 依次执行失败回调函数队列中的函数
this.onRejectedCallbacks.forEach(callback => callback(this.reason));
}
};
try {
// 执行传入的executor函数,并传入resolve和reject
executor(resolve, reject);
} catch (error) {
// 如果executor执行过程中抛出错误,调用reject
reject(error);
}
}
// 模拟then方法
MyPromise.prototype.then = function (onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === 'function'? onFulfilled : val => val;
onRejected = typeof onRejected === 'function'? onRejected : err => { throw err };
if (this.status === 'fulfilled') {
return new MyPromise((resolve, reject) => {
try {
const x = onFulfilled(this.value);
resolvePromise(this, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.status ==='rejected') {
return new MyPromise((resolve, reject) => {
try {
const x = onRejected(this.reason);
resolvePromise(this, x, resolve, reject);
} catch (error) {
reject(error);
}
});
}
if (this.status === 'pending') {
return new MyPromise((resolve, reject) => {
this.onFulfilledCallbacks.push(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(this, x, resolve, reject);
} catch (error) {
reject(error);
}
});
this.onRejectedCallbacks.push(() => {
try {
const x = onRejected(this.reason);
resolvePromise(this, x, resolve, reject);
} catch (error) {
reject(error);
}
});
});
}
};
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
if (x instanceof MyPromise) {
x.then(resolve, reject);
} else if (x!== null && (typeof x === 'object' || typeof x === 'function')) {
let called = false;
try {
const then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, err => {
if (called) return;
called = true;
reject(err);
});
} else {
resolve(x);
}
} catch (error) {
if (called) return;
called = true;
reject(error);
}
} else {
resolve(x);
}
}
1.resolve 函数的工作原理
resolve
函数的主要作用是将Promise
从pending
状态转换为fulfilled
状态,并处理传入的参数。当resolve
被调用时,参数传入后具体执行过程如下:
- 检查状态 :首先判断当前
Promise
的状态是否为pending
,只有在pending
状态下才进行状态转换。 - 更新状态和值 :将
Promise
的状态设置为fulfilled
,并将传入的参数val
赋值给this.value
,用于后续.then()
回调函数获取异步操作的结果。 - 执行回调队列 :遍历
onFulfilledCallbacks
数组,依次执行其中的回调函数,并将this.value
作为参数传入。如果在Promise
处于pending
状态时就调用了.then()
方法,对应的成功回调函数会被存入onFulfilledCallbacks
队列,在resolve
执行时触发执行。
例如:
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
const data = { message: "操作成功" };
resolve(data);
}, 1000);
});
promise.then(result => {
console.log(result);
});
上述代码中,1 秒后resolve
被调用,传入对象{ message: "操作成功" }
,Promise
状态变为fulfilled
,this.value
被赋值为该对象,随后.then()
中的回调函数执行,输出该对象。
2.reject 函数的工作原理
reject
函数的作用是将Promise
从pending
状态转换为rejected
状态,并处理传入的错误参数。当reject
被调用时,参数传入后的执行流程如下:
- 检查状态 :同样先判断
Promise
的状态是否为pending
,只有pending
状态下才会进行后续操作。 - 更新状态和原因 :将
Promise
的状态设置为rejected
,把传入的错误对象或原因err
赋值给this.reason
,用于后续.catch()
回调函数捕获错误信息。 - 执行回调队列 :遍历
onRejectedCallbacks
数组,依次执行其中的回调函数,并将this.reason
作为参数传入。若在Promise
为pending
时调用了.then()
方法且提供了失败回调,或调用了.catch()
方法,对应的回调函数会被存入onRejectedCallbacks
队列,在reject
执行时触发。
示例:
const promise = new MyPromise((resolve, reject) => {
setTimeout(() => {
const error = new Error("操作失败");
reject(error);
}, 1500);
});
promise.catch(error => {
console.error(error.message);
});
这里 1.5 秒后reject
被调用,传入Error
对象,Promise
进入rejected
状态,this.reason
被赋值为该错误对象,.catch()
中的回调函数捕获并输出错误信息。
3.特殊情况处理
- resolve 传入 Promise 对象 :当
resolve
传入的参数是另一个Promise
对象时,当前Promise
的状态会跟随传入的Promise
状态变化。在模拟实现的resolvePromise
函数中,会对这种情况进行处理,等待传入的Promise
状态确定后,再根据其结果决定当前Promise
是fulfilled
还是rejected
。 - resolve 传入带有 then 方法的对象 :如果
resolve
传入的参数是一个对象或函数,且包含then
方法,会将其视为一个类Promise
对象,调用其then
方法,并根据then
方法的执行结果来决定当前Promise
的状态 。
三、resolve 和 reject的使用
1. resolve 函数详解
resolve
函数用于将 Promise 从pending
状态转换为fulfilled
状态,意味着异步操作成功完成。当resolve
被调用时,它接收的参数会作为 Promise 解决后的值,传递给后续.then()
回调函数。
⑴.基本使用示例
// 使用resolve将Promise置为fulfilled状态
const getSuccessMessage = new Promise((resolve, reject) => {
setTimeout(() => {
const message = "异步操作成功";
resolve(message);
}, 1000);
});
getSuccessMessage.then(result => {
console.log(result);
});

在上述代码中,通过setTimeout
模拟一个异步操作,1 秒后调用resolve
函数,将字符串"异步操作成功"
作为参数传入。此时,getSuccessMessage
这个 Promise 进入fulfilled
状态,.then()
回调函数接收到该字符串并进行输出。
⑵.传入不同类型参数
resolve
的参数可以是任意合法的 JavaScript 值,包括普通值、对象、数组,甚至是另一个 Promise 对象。
-
传入普通值:
const numberPromise = new Promise((resolve, reject) => {
resolve(42);
});
numberPromise.then(value => {
console.log('接收到的数值:', value);
});

传入对象:
const userPromise = new Promise((resolve, reject) => {
const user = { name: "Alice", age: 30 };
resolve(user);
});
userPromise.then(userInfo => {
console.log('用户信息:', userInfo);
});

-
传入 Promise 对象:
const innerPromise = new Promise((innerResolve) => {
setTimeout(() => {
innerResolve("内部Promise完成");
}, 500);
});const outerPromise = new Promise((resolve, reject) => {
resolve(innerPromise);
});outerPromise.then(result => {
console.log(result);
});

当resolve
传入另一个 Promise 对象时,外部 Promise 的状态会跟随内部 Promise 的状态变化,直到内部 Promise 状态确定,外部 Promise 才会完成状态转换。
2. reject 函数详解
reject
函数用于将 Promise 从pending
状态转换为rejected
状态,表示异步操作失败。它接收的参数通常是一个错误对象,会传递给后续.catch()
回调函数用于错误处理。
⑴.基本使用示例
// 使用reject将Promise置为rejected状态
const getErrorMessage = new Promise((resolve, reject) => {
setTimeout(() => {
const error = new Error("异步操作失败");
reject(error);
}, 1500);
});
getErrorMessage.catch(error => {
console.error(error.message);
});

这里同样使用setTimeout
模拟异步操作,1.5 秒后调用reject
函数,传入一个Error
对象。getErrorMessage
这个 Promise 进入rejected
状态,.catch()
回调函数捕获到错误信息并进行输出。
⑵.自定义错误类型
除了使用内置的Error
对象,也可以自定义错误类型,以便更清晰地标识不同类型的错误。
class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}
const customPromise = new Promise((resolve, reject) => {
setTimeout(() => {
const customError = new CustomError("自定义错误发生");
reject(customError);
}, 800);
});
customPromise.catch(error => {
if (error instanceof CustomError) {
console.error('自定义错误:', error.message);
} else {
console.error('其他错误:', error.message);
}
});

通过自定义错误类型,可以在捕获错误时进行更细致的处理,增强代码的健壮性和可维护性。
3. resolve 和 reject 的组合使用
在实际场景中,异步操作可能存在成功和失败两种情况,此时就需要合理使用resolve
和reject
。以下是一个模拟网络请求的示例:
function mockFetch(url) {
return new Promise((resolve, reject) => {
const isSuccess = Math.random() > 0.3; // 模拟70%的成功率
setTimeout(() => {
if (isSuccess) {
const data = { message: `请求${url}成功` };
resolve(data);
} else {
const error = new Error(`请求${url}失败`);
reject(error);
}
}, 1000);
});
}
mockFetch('https://example.com/api')
.then(result => console.log(result))
.catch(error => console.error(error.message));

在mockFetch
函数中,通过随机数模拟网络请求的成功或失败,根据结果调用resolve
或reject
,后续通过.then()
和.catch()
分别处理成功和失败的情况。
四、Promise的方法
1. then () 方法
-
语法 :
promise.then(onFulfilled, onRejected)
-
参数
onFulfilled
:当 Promise 进入 fulfilled 状态时执行的回调函数,该函数接收 Promise 解决的值作为参数。该参数可选,如果不提供,Promise 解决的值会沿着链式调用向后传递 。onRejected
:当 Promise 进入 rejected 状态时执行的回调函数,该函数接收 Promise 被拒绝的原因作为参数。该参数可选,如果不提供,rejected 状态会传递到下一个.catch()
中处理。
-
示例
getRandomNumber
.then(value => console.log('成功获取随机数:', value))
.catch(error => console.error('获取随机数失败:', error.message));
2. catch () 方法
-
语法 :
promise.catch(onRejected)
-
参数 :
onRejected
是一个回调函数,与.then()
方法中的onRejected
作用相同,用于处理 Promise 被拒绝的情况,接收拒绝原因作为参数。 -
示例
getRandomNumber
.then(value => {
// 模拟后续可能失败的操作
if (value < 0.8) {
throw new Error('随机数不满足条件');
}
return value;
})
.catch(error => console.error('操作失败:', error.message));
3.finally () 方法
-
语法 :
promise.finally(onFinally)
-
参数 :
onFinally
是一个回调函数,无论 Promise 最终是 fulfilled 还是 rejected 状态,该函数都会执行,且不接收任何参数。 -
示例
getRandomNumber
.then(value => console.log('成功获取随机数:', value))
.catch(error => console.error('获取随机数失败:', error.message))
.finally(() => console.log('Promise操作已结束'));
4.Promise.all () 方法
-
语法 :
Promise.all(iterable)
-
参数 :
iterable
是一个可迭代对象,比如数组,数组中的每个元素都应该是一个 Promise 对象。 -
返回值与执行逻辑
- 当
iterable
中的所有 Promise 都变为 fulfilled 状态时,Promise.all()
返回的 Promise 才会进入 fulfilled 状态,其解决值是一个数组,数组元素按iterable
中 Promise 的顺序对应每个 Promise 的解决值。 - 只要
iterable
中有一个 Promise 进入 rejected 状态,Promise.all()
返回的 Promise 就会立即进入 rejected 状态,其拒绝原因是第一个进入 rejected 状态的 Promise 的拒绝原因。
- 当
-
示例
const promise1 = new Promise((resolve) => setTimeout(() => resolve(1), 1000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve(2), 1500));
const promise3 = new Promise((_, reject) => setTimeout(() => reject(new Error('Promise3失败')), 500));Promise.all([promise1, promise2, promise3])
.then(values => console.log('所有Promise成功:', values))
.catch(error => console.error('有Promise失败:', error.message));
5. Promise.race () 方法
-
语法 :
Promise.race(iterable)
-
参数:同样接收一个可迭代对象,元素为 Promise 对象。
-
返回值与执行逻辑 :
Promise.race()
返回的 Promise 会在iterable
中任意一个 Promise 率先改变状态(无论是 fulfilled 还是 rejected)时,随之改变状态。其状态和值与率先改变状态的 Promise 一致。 -
示例
const promiseA = new Promise((resolve) => setTimeout(() => resolve('A完成'), 2000));
const promiseB = new Promise((resolve) => setTimeout(() => resolve('B完成'), 1000));Promise.race([promiseA, promiseB])
.then(result => console.log('率先完成的结果:', result));
6. Promise.resolve () 方法
-
语法 :
Promise.resolve(value)
-
参数 :
value
可以是任意合法的 JavaScript 值,包括 Promise 对象、普通值。 -
返回值与执行逻辑
- 如果
value
是一个 Promise 对象,直接返回该 Promise 对象。 - 如果
value
是一个普通值,返回一个新的已解决状态(fulfilled)的 Promise 对象,其解决值为value
。
- 如果
-
示例
const resolvedPromise = Promise.resolve(42);
const existingPromise = new Promise((resolve) => resolve('已存在的Promise'));resolvedPromise.then(value => console.log('普通值转换的Promise:', value));
Promise.resolve(existingPromise).then(value => console.log('Promise转换的Promise:', value));
7.Promise.reject () 方法
-
语法 :
Promise.reject(reason)
-
参数 :
reason
通常是一个错误对象,用于表示 Promise 被拒绝的原因。 -
返回值与执行逻辑 :返回一个已拒绝状态(rejected)的 Promise 对象,其拒绝原因就是传入的
reason
参数。 -
示例
const rejectedPromise = Promise.reject(new Error('手动拒绝的Promise'));
rejectedPromise.catch(error => console.error('Promise被拒绝:', error.message));
五、async await
async
和 await
是 JavaScript 里用于处理异步操作的语法糖,它们构建于 Promise 之上,能让异步代码以同步的形式书写,增强代码的可读性与可维护性。下面为你详细介绍:
1. async
函数
借助 async
关键字可定义异步函数,该函数会自动返回一个 Promise 对象。当函数执行完毕时,返回值会被包装进 Promise 的 resolve
中;若函数抛出异常,异常会被包装进 Promise 的 reject
中。
async function exampleAsyncFunction() {
return 'Hello, World!';
}
exampleAsyncFunction().then(result => {
console.log(result); // 输出: Hello, World!
});

2.await
表达式
await
仅能在 async
函数内部使用。它会暂停 async
函数的执行,直至所等待的 Promise 被解决(resolved)或者被拒绝(rejected),之后才会恢复 async
函数的执行,并返回 Promise 的解决值。
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function exampleWithAwait() {
console.log('Before await');
await delay(2000); // 等待 2 秒
console.log('After await');
}
exampleWithAwait();
3. 处理错误
在 async
函数里,可以使用 try...catch
语句来处理 await
表达式可能出现的错误。
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('Data fetch failed'));
}, 1000);
});
}
async function handleError() {
try {
await fetchData();
} catch (error) {
console.error('Error:', error.message);
}
}
handleError();
4. 并行处理
尽管 await
会暂停函数的执行,但你能够通过 Promise.all
来并行处理多个异步操作。
function asyncTask1() {
return new Promise(resolve => setTimeout(() => resolve('Task 1 completed'), 1000));
}
function asyncTask2() {
return new Promise(resolve => setTimeout(() => resolve('Task 2 completed'), 1500));
}
async function parallelTasks() {
const [result1, result2] = await Promise.all([asyncTask1(), asyncTask2()]);
console.log(result1);
console.log(result2);
}
parallelTasks();
通过 async
和 await
,异步代码的编写和理解变得更加容易,就像同步代码一样直观。