手写PromiseA+规范及应用实例分析
2024-01-26 05:02:21
在繁杂的编程世界里,异步编程无疑是一股清流,它让我们得以在主线程之外执行任务,从而提高程序的执行效率。在JavaScript中,Promise便是异步编程的利器,它提供了一套规范,帮助开发者轻松处理异步操作。
邂逅PromiseA+规范,领略异步之美
PromiseA+规范是一套用于Promise实现的标准,它定义了Promise的基本行为和用法。只有遵循此规范实现的Promise才能被称为真正的Promise。
1. Promise的三种状态
每个Promise实例都有三种状态:Pending(等待)、Fulfilled(已完成)和Rejected(已拒绝)。Pending状态表示Promise还没有完成,Fulfilled状态表示Promise已成功完成,而Rejected状态表示Promise已失败。
2. Promise的链式调用
Promise支持链式调用,即在一个Promise中可以返回另一个Promise,从而形成一个Promise链。链式调用可以帮助我们更轻松地处理复杂的操作流程,提高代码的可读性和可维护性。
3. Promise.all
Promise.all方法可以同时执行多个Promise并等待所有Promise完成,然后将所有Promise的结果作为参数传递给回调函数。Promise.all非常适合处理需要同时执行多个异步操作的情况。
4. Promise.race
Promise.race方法可以同时执行多个Promise,但它只等待第一个完成的Promise,然后将该Promise的结果作为参数传递给回调函数。Promise.race非常适合处理需要竞争执行的异步操作。
5. Promise.resolve
Promise.resolve方法可以将一个值包装成一个Fulfilled状态的Promise。如果传入一个Promise实例,Promise.resolve方法将直接返回该Promise实例。
6. Promise.reject
Promise.reject方法可以将一个值包装成一个Rejected状态的Promise。如果传入一个Promise实例,Promise.reject方法将直接返回该Promise实例。
亲自操刀,手写Promise
手写Promise的过程可以帮助我们更深入地理解Promise的实现原理,同时也是对自身编程能力的挑战和提升。
1. 定义Promise类
class Promise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.reason = undefined;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
try {
executor(this.resolve.bind(this), this.reject.bind(this));
} catch (error) {
this.reject(error);
}
}
resolve(value) {
if (this.state !== 'pending') {
return;
}
this.state = 'fulfilled';
this.value = value;
this.onFulfilledCallbacks.forEach((callback) => {
callback(value);
});
}
reject(reason) {
if (this.state !== 'pending') {
return;
}
this.state = 'rejected';
this.reason = reason;
this.onRejectedCallbacks.forEach((callback) => {
callback(reason);
});
}
then(onFulfilled, onRejected) {
const promise2 = new Promise((resolve, reject) => {
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const x = onFulfilled(this.value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const x = onRejected(this.reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
} else {
this.onFulfilledCallbacks.push((value) => {
setTimeout(() => {
try {
const x = onFulfilled(value);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push((reason) => {
setTimeout(() => {
try {
const x = onRejected(reason);
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
return promise2;
}
catch(onRejected) {
return this.then(undefined, onRejected);
}
finally(onFinally) {
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
try {
onFinally();
resolve(this.value);
} catch (error) {
reject(error);
}
}, 0);
});
return promise2;
}
static resolve(value) {
return new Promise((resolve) => {
resolve(value);
});
}
static reject(reason) {
return new Promise((_, reject) => {
reject(reason);
});
}
static all(promises) {
return new Promise((resolve, reject) => {
const results = [];
let count = 0;
promises.forEach((promise, index) => {
promise.then(
(value) => {
results[index] = value;
count++;
if (count === promises.length) {
resolve(results);
}
},
(reason) => {
reject(reason);
}
);
});
});
}
static race(promises) {
return new Promise((resolve, reject) => {
promises.forEach((promise) => {
promise.then(
(value) => {
resolve(value);
},
(reason) => {
reject(reason);
}
);
});
});
}
}
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
reject(new TypeError('Chaining cycle detected for promise'));
}
if (x instanceof Promise) {
x.then(
(value) => {
resolvePromise(promise2, value, resolve, reject);
},
(reason) => {
reject(reason);
}
);
} else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
try {
const then = x.then;
if (typeof then === 'function') {
then.call(
x,
(y) => {
resolvePromise(promise2, y, resolve, reject);
},
(reason) => {
reject(reason);
}
);
} else {
resolve(x);
}
} catch (error) {
reject(error);
}
} else {
resolve(x);
}
}
2. Promise的使用示例
// 创建一个Promise实例
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('Hello, Promise!');
}, 1000);
});
// 使用then方法处理Promise的结果
promise.then((result) => {
console.log(result); // 输出: Hello, Promise!
});
// 使用catch方法处理Promise的失败
promise.catch((error) => {
console.log(error); // 输出: Error: Something went wrong!
});
// 使用finally方法无论Promise成功还是失败都会执行
promise.finally(() => {
console.log('Finally!'); // 输出: Finally!
});
// 使用Promise.all方法同时执行多个Promise
const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);
Promise.all([promise1, promise2, promise3]).then((results) => {
console.log(results); // 输出: [1, 2, 3]
});
// 使用Promise.