When.js 核心 API 详解与最佳实践
前言
When.js 是一个轻量级的 Promises/A+ 实现库,提供了丰富的异步编程工具集。本文将深入解析 When.js 的核心 API 及其使用场景,帮助开发者更好地掌握 Promise 编程范式。
核心概念
Promise 是什么
Promise 是对异步操作结果的代理对象,它代表一个可能现在、也可能未来才可用的值。通过 Promise,我们可以用同步的编程风格来处理异步操作,避免回调地狱。
核心 API 解析
1. 基础创建与转换
when() 函数
when()
是 When.js 的核心入口函数,用于将任意值转换为可信 Promise:
// 将值转换为已完成的 Promise
const promise1 = when(42);
// 将其他 Promise 转换为 When.js Promise
const promise2 = when($.ajax('/data'));
// 带转换函数的用法
const promise3 = when(value, x => x * 2);
最佳实践:
- 使用
when()
包装不确定是否为 Promise 的值 - 在与其他 Promise 库混用时,用
when()
进行标准化
when.try() 方法
安全执行函数并返回 Promise:
// 安全执行可能抛出异常的函数
when.try(() => JSON.parse(jsonStr))
.catch(e => console.error("解析失败", e));
特点:
- 自动捕获同步异常
- 支持 Promise 参数自动解包
- 替代
new Promise
的更简洁方式
when.lift() 方法
创建 Promise 化函数:
const safeParse = when.lift(JSON.parse);
// 可重复使用
safeParse('{"a":1}').then(console.log);
safeParse('invalid').catch(console.error);
适用场景:
- 将现有同步函数改造为 Promise 风格
- 创建可复用的安全函数
2. Promise 组合
when.join() 方法
合并多个 Promise 为一个:
when.join(getUser(), getProfile())
.then(([user, profile]) => {
// 处理合并结果
});
对比 when.all():
join
接受多个参数all
接受数组参数- 功能等价,按场景选择更合适的 API
when.promise() 构造函数
显式创建 Promise:
const promise = when.promise((resolve, reject) => {
asyncOperation((err, result) => {
if (err) reject(err);
else resolve(result);
});
});
注意事项:
- 优先考虑
when.try
或when.lift
- 仅在不适合使用上述方法时才用此 API
3. 状态控制
when.resolve() 与 when.reject()
快速创建已解决/已拒绝的 Promise:
// 快速返回成功结果
function cachedData() {
return cache.hasData
? when.resolve(cache.data)
: fetchData();
}
// 快速返回错误
function validate(input) {
return !input
? when.reject(new Error("输入不能为空"))
: process(input);
}
Promise 实例方法
1. 结果处理
then() 与 done() 对比
| 方法 | 返回值 | 错误处理 | 适用场景 | |------|--------|----------|----------| | then() | 新 Promise | 链式捕获 | 转换/组合 Promise | | done() | undefined | 抛出异常 | 最终消费结果 |
示例对比:
// 转换场景 - 使用 then
function getProcessedData() {
return fetchData()
.then(transform)
.then(validate);
}
// 消费场景 - 使用 done
getProcessedData().done(
result => display(result),
error => showError(error)
);
spread() 方法
展开数组结果:
fetchMultipleItems().spread((item1, item2) => {
// 直接使用解构参数
});
等价于:
fetchMultipleItems()
.then(items => when.all(items))
.then(([item1, item2]) => {...});
2. 错误处理
catch() 高级用法
条件错误捕获:
apiCall()
.catch(NetworkError, e => retry())
.catch(ValidationError, e => log())
.catch(e => fallback());
优势:
- 比传统 try/catch 更清晰
- 支持错误类型分类处理
- 保持错误处理代码靠近可能抛出错误的代码
finally() 方法
资源清理:
let resource;
getResource()
.then(r => { resource = r; })
.finally(() => {
if (resource) resource.release();
});
特点:
- 无论成功失败都会执行
- 不影响 Promise 链的结果传递
- 适合执行清理操作
高级模式
Promise 折叠 (fold)
组合两个 Promise:
// 使用现有函数组合 Promise
const total = price.fold(add, tax);
// 等价于
const total = when.join(price, tax)
.then(([p, t]) => p + t);
优势:
- 复用现有二元函数
- 避免临时数组创建
- 更直观的表达意图
进度通知 (已废弃)
// 旧版进度通知 (已废弃)
uploadFile()
.progress(p => updateProgressBar(p))
.then(finish);
替代方案:
- 使用事件或 Observable
- 拆分多个 Promise 表示不同阶段
最佳实践总结
-
错误处理原则:
- 要么 return Promise 传递错误
- 要么 done() 处理错误
-
API 选择指南:
- 简单转换:then()
- 错误处理:catch()
- 资源清理:finally()
- 结果消费:done()
-
性能优化:
- 避免不必要的 Promise 包装
- 提前创建重用 lifted 函数
- 使用 join/all 并行执行独立操作
-
代码可读性:
- 保持 Promise 链垂直对齐
- 命名中间 Promise 变量
- 合理使用缩进表达层级
通过掌握这些核心 API 和模式,开发者可以构建出健壮、可维护的异步 JavaScript 应用。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考