引言
在JavaScript中,异步编程是一个常见的需求。传统的回调函数方式容易导致“回调地狱”,使代码难以维护。为了解决这个问题,ES6引入了Promise对象,用于更优雅地处理异步操作。本文将介绍Promise的状态、方法,并展示如何在JavaScript中封装Promise,实现其核心方法,并在Function原型链中实现这些方法。
Promise状态介绍
Promise对象有三种状态:
- Pending(待定):初始状态,既不是成功也不是失败。
- Fulfilled(已兑现):操作成功完成。
- Rejected(已拒绝):操作失败。
状态一旦改变,就不能再变。Promise对象从Pending状态变为Fulfilled或Rejected状态后,会调用相应的处理函数。
Promise方法介绍
Promise对象有以下几种方法:
- then(onFulfilled, onRejected):添加成功和失败的回调函数。
- catch(onRejected):添加失败的回调函数。
- resolve(value):返回一个状态为Fulfilled的Promise对象。
- reject(reason):返回一个状态为Rejected的Promise对象。
- all(promises):接收一个Promise数组,返回一个新的Promise,只有当所有Promise都成功时才成功。
- race(promises):接收一个Promise数组,返回一个新的Promise,哪个Promise先完成就返回哪个Promise的结果。
封装Promise
下面是一个在JavaScript中封装Promise的实现,并在Function原型链中实现其核心方法。
class MyPromise {
constructor(executor) {
// 初始状态为 pending
this.state = 'pending';
// 成功的值
this.value = undefined;
// 失败的原因
this.reason = undefined;
// 成功回调函数队列
this.onFulfilledCallbacks = [];
// 失败回调函数队列
this.onRejectedCallbacks = [];
// resolve 函数
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
// 执行所有成功回调
this.onFulfilledCallbacks.forEach(fn => fn());
}
};
// reject 函数
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
// 执行所有失败回调
this.onRejectedCallbacks.forEach(fn => fn());
}
};
// 执行 executor 函数,并传入 resolve 和 reject
try {
executor(resolve, reject);
} catch (err) {
reject(err);
}
}
// then 方法
then(onFulfilled, onRejected) {
// 如果 onFulfilled 不是函数,给一个默认函数,返回 value
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
// 如果 onRejected 不是函数,给一个默认函数,抛出 reason
onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };
// 返回一个新的 Promise
let promise2 = new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
// 异步执行 onFulfilled
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// 解析 x
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.state === 'rejected') {
// 异步执行 onRejected
setTimeout(() => {
try {
let x = onRejected(this.reason);
// 解析 x
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
}
if (this.state === 'pending') {
// 如果状态是 pending,将 onFulfilled 和 onRejected 存入队列
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
let x = onFulfilled(this.value);
// 解析 x
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
let x = onRejected(this.reason);
// 解析 x
resolvePromise(promise2, x, resolve, reject);
} catch (err) {
reject(err);
}
});
});
}
});
return promise2;
}
// catch 方法
catch(onRejected) {
return this.then(null, onRejected);
}
// 静态 resolve 方法
static resolve(value) {
return new MyPromise((resolve, reject) => {
resolve(value);
});
}
// 静态 reject 方法
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
// 静态 all 方法
static all(promises) {
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
function processData(index, data) {
result[index] = data;
if (++count === promises.length) {
resolve(result);
}
}
for (let i = 0; i < promises.length; i++) {
promises[i].then(data => {
processData(i, data);
}, reject);
}
});
}
// 静态 race 方法
static race(promises) {
return new MyPromise((resolve, reject) => {
for (let i = 0; i < promises.length; i++) {
promises[i].then(resolve, reject);
}
});
}
}
// 解析 Promise 的结果
function resolvePromise(promise2, x, resolve, reject) {
// 如果 promise2 和 x 指向同一个对象,抛出类型错误,防止循环引用
if (promise2 === x) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 用于标记是否已经调用过 resolve 或 reject,防止多次调用
let called;
// 如果 x 不为 null 且 x 是对象或函数
if (x != null && (typeof x === 'object' || typeof x === 'function')) {
try {
// 尝试取 x.then,可能会抛出错误
let then = x.then;
// 如果 then 是函数,认为 x 是一个 promise
if (typeof then === 'function') {
// 调用 then,并将 this 指向 x
then.call(x, y => {
// 如果已经调用过 resolve 或 reject,直接返回
if (called) return;
called = true;
// 递归解析 y,防止 y 也是一个 promise
resolvePromise(promise2, y, resolve, reject);
}, err => {
// 如果已经调用过 resolve 或 reject,直接返回
if (called) return;
called = true;
// 如果出错,直接 reject
reject(err);
});
} else {
// 如果 then 不是函数,说明 x 不是一个 promise,直接 resolve
resolve(x);
}
} catch (err) {
// 如果取 then 时抛出错误,且没有调用过 resolve 或 reject,直接 reject
if (called) return;
called = true;
reject(err);
}
} else {
// 如果 x 不是对象或函数,直接 resolve
resolve(x);
}
}
// 在Function原型链中实现
Function.prototype.resolve = MyPromise.resolve;
Function.prototype.reject = MyPromise.reject;
Function.prototype.all = MyPromise.all;
Function.prototype.race = MyPromise.race;
// 使用方法
const promise1 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 1 resolved');
}, 1000);
});
const promise2 = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('Promise 2 resolved');
}, 2000);
});
promise1.then(value => {
console.log(value);
return promise2;
}).then(value => {
console.log(value);
}).catch(err => {
console.error(err);
});
MyPromise.all([promise1, promise2]).then(values => {
console.log('All promises resolved:', values);
}).catch(err => {
console.error(err);
});
MyPromise.race([promise1, promise2]).then(value => {
console.log('Race winner:', value);
}).catch(err => {
console.error(err);
});
详细描述
-
构造函数:
constructor(executor) { this.state = 'pending'; this.value = undefined; this.reason = undefined; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = [];初始化Promise的状态为
pending,并定义成功值、失败原因和回调函数队列。 -
resolve函数:
const resolve = (value) => { if (this.state === 'pending') { this.state = 'fulfilled'; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn()); } };将Promise的状态从
pending变为fulfilled,并执行所有成功回调。 -
reject函数:
const reject = (reason) => { if (this.state === 'pending') { this.state = 'rejected'; this.reason = reason; this.onRejectedCallbacks.forEach(fn => fn()); } };将Promise的状态从
pending变为rejected,并执行所有失败回调。 -
then方法:
then(onFulfilled, onRejected) { onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value; onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason };then方法接收两个回调函数,并返回一个新的Promise。 -
catch方法:
catch(onRejected) { return this.then(null, onRejected); }catch方法是then方法的语法糖,只接收失败回调。 -
静态resolve方法:
static resolve(value) { return new MyPromise((resolve, reject) => { resolve(value); }); }返回一个状态为
fulfilled的Promise。 -
静态reject方法:
static reject(reason) { return new MyPromise((resolve, reject) => { reject(reason); }); }返回一个状态为
rejected的Promise。 -
静态all方法:
static all(promises) { return new MyPromise((resolve, reject) => { let result = []; let count = 0; function processData(index, data) { result[index] = data; if (++count === promises.length) { resolve(result); } } for (let i = 0; i < promises.length; i++) { promises[i].then(data => { processData(i, data); }, reject); } }); }接收一个Promise数组,只有当所有Promise都成功时才成功。
-
静态race方法:
static race(promises) { return new MyPromise((resolve, reject) => { for (let i = 0; i < promises.length; i++) { promises[i].then(resolve, reject); } }); }接收一个Promise数组,哪个Promise先完成就返回哪个Promise的结果。
-
resolvePromise函数:
function resolvePromise(promise2, x, resolve, reject) { // 如果 promise2 和 x 指向同一个对象,抛出类型错误,防止循环引用 if (promise2 === x) { return reject(new TypeError('Chaining cycle detected for promise')); } // 用于标记是否已经调用过 resolve 或 reject,防止多次调用 let called; // 如果 x 不为 null 且 x 是对象或函数 if (x != null && (typeof x === 'object' || typeof x === 'function')) { try { // 尝试取 x.then,可能会抛出错误 let then = x.then; // 如果 then 是函数,认为 x 是一个 promise if (typeof then === 'function') { // 调用 then,并将 this 指向 x then.call(x, y => { // 如果已经调用过 resolve 或 reject,直接返回 if (called) return; called = true; // 递归解析 y,防止 y 也是一个 promise resolvePromise(promise2, y, resolve, reject); }, err => { // 如果已经调用过 resolve 或 reject,直接返回 if (called) return; called = true; // 如果出错,直接 reject reject(err); }); } else { // 如果 then 不是函数,说明 x 不是一个 promise,直接 resolve resolve(x); } } catch (err) { // 如果取 then 时抛出错误,且没有调用过 resolve 或 reject,直接 reject if (called) return; called = true; reject(err); } } else { // 如果 x 不是对象或函数,直接 resolve resolve(x); } }这个函数用于解析Promise的结果,处理Promise链中的值,防止循环引用,并确保Promise的状态只改变一次。
使用场景和返回结果
-
then方法:
- 使用场景:处理Promise成功或失败的结果。
- 返回结果:返回一个新的Promise,可以链式调用。
promise1.then(value => { console.log(value); // Promise 1 resolved return promise2; }).then(value => { console.log(value); // Promise 2 resolved }).catch(err => { console.error(err); }); -
catch方法:
- 使用场景:处理Promise失败的结果。
- 返回结果:返回一个新的Promise,可以链式调用。
promise1.catch(err => { console.error(err); }); -
静态resolve方法:
- 使用场景:创建一个状态为
fulfilled的Promise。 - 返回结果:返回一个状态为
fulfilled的Promise。
MyPromise.resolve('Success').then(value => { console.log(value); // Success }); - 使用场景:创建一个状态为
-
静态reject方法:
- 使用场景:创建一个状态为
rejected的Promise。 - 返回结果:返回一个状态为
rejected的Promise。
MyPromise.reject('Error').catch(reason => { console.error(reason); // Error }); - 使用场景:创建一个状态为
-
静态all方法:
- 使用场景:等待所有Promise都成功。
- 返回结果:返回一个新的Promise,只有当所有Promise都成功时才成功。
MyPromise.all([promise1, promise2]).then(values => { console.log('All promises resolved:', values); // All promises resolved: ['Promise 1 resolved', 'Promise 2 resolved'] }).catch(err => { console.error(err); }); -
静态race方法:
- 使用场景:等待第一个完成的Promise。
- 返回结果:返回一个新的Promise,哪个Promise先完成就返回哪个Promise的结果。
MyPromise.race([promise1, promise2]).then(value => { console.log('Race winner:', value); // Race winner: Promise 1 resolved }).catch(err => { console.error(err); });
通过详细的注释和解释,希望你能更好地理解MyPromise类及其resolvePromise函数的实现原理,以及每个方法的使用场景和返回结果。
找到具有 1 个许可证类型的类似代码