原文合集地址如下,有需要的朋友可以关注
什么是Promise
当谈论 Promise 时,可以将其比喻为一种承诺或契约,用于处理异步操作的结果。异步操作是指那些不会立即完成的操作,比如从服务器获取数据、读取文件、发送网络请求等等。通常情况下,这些操作需要一定的时间来完成。
Promise 的主要目的是在异步操作完成后,通过 Promise 对象来获取操作的结果或处理操作的失败情况。Promise 可以有三种状态:进行中(Pending)、已成功(Fulfilled)和已失败(Rejected)。
进行中(Pending):Promise 刚被创建时的初始状态,表示异步操作正在进行中,尚未完成或失败。
已成功(Fulfilled):当异步操作成功完成时,Promise 的状态变为已成功,同时携带着异步操作的结果值。
已失败(Rejected):当异步操作失败时,Promise 的状态变为已失败,同时携带着失败的原因,通常是一个错误对象。
创建一个 Promise对象需要使用 new Promise()
构造函数,它接收一个带有 resolve
和 reject
两个参数的执行函数作为参数:
const myPromise = new Promise((resolve, reject) => {
// 异步操作(例如,从服务器获取数据或读取文件)
// 如果异步操作成功,调用 resolve 并传递结果值
// 如果异步操作失败,调用 reject 并传递失败原因
});
resolve
函数用于将 Promise 状态从进行中转换为已成功,而 reject
函数用于将状态从进行中转换为已失败。
一旦创建了 Promise 对象,就可以通过使用 .then()
方法来添加异步操作成功的回调,并使用 .catch()
方法来添加异步操作失败的回调:
myPromise.then((result) => {
// 异步操作成功,获取 result 结果值
}).catch((error) => {
// 异步操作失败,获取 error 失败原因
});
Promise 还支持链式调用,
可以通过多次使用 .then()
方法来串联多个异步操作:
myPromise.then((result) => {
// 第一个异步操作成功,获取 result 结果值
// 返回一个新的 Promise 对象
return anotherAsyncOperation(result);
}).then((anotherResult) => {
// 第二个异步操作成功,获取 anotherResult 结果值
}).catch((error) => {
// 如果任何一个异步操作失败,获取 error 失败原因
});
Promise 的主要方法:
Promise.prototype.then(onFulfilled, onRejected)
:用于添加异步操作成功(Fulfilled)和失败(Rejected)的回调函数。onFulfilled 是异步操作成功时的回调函数,接收成功的结果值作为参数;onRejected 是异步操作失败时的回调函数,接收失败的原因作为参数。Promise.prototype.catch(onRejected)
:用于添加异步操作失败的回调函数,相当于.then(null, onRejected)
。Promise.prototype.finally(onFinally)
:在 Promise 的状态变为 Fulfilled 或 Rejected 时,都会执行onFinally
回调函数。该方法不接收任何参数,它返回一个新的 Promise 对象,该 Promise 对象的状态和值与原始 Promise 对象一致。Promise.resolve(value)
:返回一个以给定值value
解析的 Promise 对象。如果value
是一个 Promise 对象,则直接返回它;如果value
是一个 thenable 对象(即具有then
方法的对象),则会将它转换成一个 Promise 对象并返回。Promise.reject(reason)
:返回一个以给定原因reason
拒绝的 Promise 对象。
下面是一个简单的示例,展示如何使用 Promise 来处理异步操作:
function fetchUserData() {
return new Promise((resolve, reject) => {
// 模拟异步请求
setTimeout(() => {
const userData = {
name: 'John', age: 30 };
// 模拟异步请求成功
resolve(userData);
// 模拟异步请求失败
// reject(new Error('Failed to fetch user data'));
}, 1000);
});
}
// 使用 Promise
fetchUserData()
.then((userData) => {
console.log('用户信息:', userData);
})
.catch((error) => {
console.error('错误:', error.message);
})
.finally(() => {
console.log('异步操作完成');
});
在上面的示例中,fetchUserData
函数返回一个 Promise 对象,该 Promise 对象模拟了一个异步请求,1秒后成功完成,并返回一个用户信息对象。可以使用 .then
方法添加成功回调,并使用 .catch
方法添加失败回调。在 finally
回调中,无论异步操作成功或失败,都会执行 finally
中的代码。
Promise.all(iterable)
:该方法接收一个可迭代对象(例如数组)作为参数,其中的每个元素都是 Promise 对象。它返回一个新的 Promise 对象,该 Promise 对象在所有输入的 Promise 都成功完成时才会成功,并将成功的结果值作为数组返回,如果有任何一个输入的 Promise 失败,则返回失败的原因。
const promise1 = Promise.resolve(1);
const promise2 = new Promise((resolve) => setTimeout(() => resolve(2), 1000));
const promise3 = fetch('https://api.example.com/data');
Promise.all([promise1, promise2, promise3])
.then((results) => {
console.log('所有 Promise 都成功完成,结果值:', results);
})
.catch((error) => {
console.error('其中一个 Promise 失败,原因:', error);
});
Promise.allSettled(iterable)
:该方法与Promise.all
类似,接收一个可迭代对象作为参数,返回一个新的 Promise 对象,在所有输入的 Promise 都完成(无论成功或失败)时才会成功。它将以包含每个 Promise 的结果状态的对象数组进行解析,每个对象都有一个status
字段,可能的值是"fulfilled"
或"rejected"
,以及一个value
或reason
字段分别包含了成功的结果值或失败的原因。
const promise1 = Promise.resolve(1);
const promise2 = Promise.reject(new Error('Rejected promise'));
const promise3 = new Promise((resolve) => setTimeout(() => resolve(3), 2000));
Promise.allSettled([promise1, promise2, promise3])
.then((results) => {
console.log('所有 Promise 完成(成功或失败),结果:', results);
});
Promise.race(iterable)
:该方法与Promise.all
类似,接收一个可迭代对象作为参数,返回一个新的 Promise 对象,该 Promise 对象在输入的 Promise 中有任意一个完成(成功或失败)时就会完成,并将完成的结果值或失败的原因传递给回调。
const promise1 = new Promise((resolve) => setTimeout(() => resolve('Promise 1'), 1000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve('Promise 2'), 2000));
Promise.race([promise1, promise2])
.then((result) => {
console.log('第一个完成的 Promise 结果:', result);
});
promise优势与弊端
Promise 的作用和优点:
处理异步操作:Promise 是 JavaScript 中处理异步操作的一种标准方式。它提供了一种优雅的方式来管理和处理异步代码,避免了回调地狱(Callback Hell)问题,使代码更易读、维护和理解。
优化性能:Promise 可以帮助优化性能,避免不必要的函数创建和组件重新渲染。使用
Promise.all
或Promise.race
等方法可以处理多个异步操作,等待它们全部完成或只要有一个完成即可,提高应用的性能和响应性。异常处理:Promise 允许通过
.catch
方法统一处理异步操作的错误,使错误处理更加方便和一致。它还可以通过try/catch
语句处理同步代码中的异常,使异常处理更加统一和简洁。支持链式调用:Promise 的
.then
和.catch
方法支持链式调用,可以方便地对多个异步操作进行串联和组合。可以通过
Promise.resolve
和Promise.reject
方法创建已解决或已拒绝的 Promise,方便进行异步操作的初始化。
Promise 的弊端:
不支持取消:Promise 一旦创建,就无法取消或终止它的执行。一旦 Promise 进入 Pending 状态,它会继续执行,无法中途停止。
无法处理多个结果:Promise 只能解决一次,一旦 Promise 进入 Fulfilled 或 Rejected 状态,它的状态就不会改变。因此,它无法处理需要多次结果的场景。
不支持超时:Promise 本身不支持超时设置,无法直接控制异步操作的超时时间。
回调地狱的替代方案:虽然 Promise 解决了回调地狱的问题,但是当 Promise 的链式调用过于复杂时,可能会导致代码嵌套和可读性降低。
需要兼容性处理:在某些较旧的浏览器中,可能需要进行 Promise 的兼容性处理,或者使用 polyfill 来支持 Promise。
手写实现一个Promise
class MyPromise {
constructor(executor) {
// 初始化 Promise 的状态和值
this.state = 'pending';
this.value = undefined;
// 定义 resolve 和 reject 函数
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
}
};
const reject = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.value = reason;
}
};
try {
// 执行 executor 函数,并传入 resolve 和 reject 函数
executor(resolve, reject);
} catch (error) {
// 如果执行过程中捕获到异常,将 Promise 状态改为 rejected
reject(error);
}
}
then(onFulfilled, onRejected) {
// 如果没有传入 onFulfilled 或 onRejected,则创建一个默认的函数来传递值或原因
onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : (value) => value;
onRejected = typeof onRejected === 'function' ? onRejected : (reason) => {
throw reason; };
return new MyPromise((resolve, reject) => {
// 根据 Promise 的状态执行对应的回调函数
if (this.state === 'fulfilled') {
setTimeout(() => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'rejected') {
setTimeout(() => {
try {
const result = onRejected(this.value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
} else if (this.state === 'pending') {
// 如果 Promise 的状态还是 pending,将回调函数添加到待处理队列中
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const result = onRejected(this.value);
resolve(result);
} catch (error) {
reject(error);
}
}, 0);
});
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
// 示例用法:
const myPromise = new MyPromise((resolve, reject) => {
setTimeout(() => {
const random = Math.random();
if (random > 0.5) {
resolve('Success!');
} else {
reject(new Error('Failed!'));
}
}, 1000);
});
myPromise
.then((result) => {
console.log('Fulfilled:', result);
return 'Resolved Value';
})
.then((value) => {
console.log('Chained then:', value);
})
.catch((error) => {
console.error('Rejected:', error);
});
这个简化的 Promise 实现包含 resolve 和 reject 函数、then 方法、catch 方法,以及对异步操作的处理。这个实现并没有处理异步回调函数的执行顺序,真实的 Promise 实现还需要处理更多细节,例如异步操作的执行、错误处理、Promise 链的调用顺序等。完整的 Promise 实现需要更复杂的处理逻辑和边界情况的考虑。