开发者应专注于业务逻辑,而非 Promise API 的细节。
传统 Promise 组合(如 Promise.all、Promise.race)的命名与语义不够直观,尤其在复杂异步场景下,代码可读性迅速下降。
promise-logic 通过逻辑门(Logic Gate) 的方式,将异步组合抽象为 and、or、xor 等逻辑操作,使代码语义清晰、逻辑自解释。
示例场景:电商订单处理
import { PromiseLogic } from 'promise-logic';
// 订单处理流程
async function createOrder() {
// 统一错误类型
const PAYMENT_OR_INVENTORY_ERROR = 'PAYMENT_OR_INVENTORY_ERROR';
const ORDER_ERROR = 'ORDER_ERROR';
const LOGISTICS_ERROR = 'LOGISTICS_ERROR';
const COUPON_ERROR = 'COUPON_ERROR';
// 从 PromiseLogic 解构 and, or 方法,以获得更简洁的语法并理解当前场景的逻辑关系
const { and, or } = PromiseLogic;
try {
// 执行支付和库存操作(两者必须都成功)
const [
[paymentResult, inventoryResult], // 支付和库存操作结果
logistics, // 物流操作结果
coupon // 优惠券操作结果
] = await and([
and([paymentAPI(), inventoryAPI()], {
errorType: PAYMENT_OR_INVENTORY_ERROR, // 自定义支付或库存错误类型
}),
or([oneLogisticsAPI(), twoLogisticsAPI()], {
errorType: LOGISTICS_ERROR, // 自定义物流错误类型
}),
or([couponAPI1(), couponAPI2()], {
errorType: COUPON_ERROR, // 自定义优惠券错误类型
})
], {
errorType: ORDER_ERROR, // 自定义订单错误类型
errorMessage: '订单创建失败' // 自定义订单错误信息
});
// 订单创建成功,返回支付结果、库存结果、物流结果和优惠券结果
return {
payment: paymentResult,
inventory: inventoryResult,
logistics: logistics,
coupon: coupon,
status: 'success'
};
} catch (error) {
// 分析错误类型
switch (error.type) {
case ORDER_ERROR:
return {
status: 'error',
errorType: 'order_error',
message: '订单创建失败',
details: error
};
case PAYMENT_OR_INVENTORY_ERROR:
return {
status: 'error',
errorType: 'payment_or_inventory_failed',
message: '支付或库存操作失败',
details: error
};
case LOGISTICS_ERROR:
return {
status: 'error',
errorType: 'logistics_unavailable',
message: '所有物流服务均不可用',
details: error
};
case COUPON_ERROR:
return {
status: 'error',
errorType: 'coupon_error',
message: '所有优惠券均不可用',
details: error
};
default:
return {
status: 'error',
errorType: 'default_error',
message: '订单创建过程中发生未知错误',
details: error
};
}
}
}
可以看到,代码结构与业务规则完全一致,代码即是文档,逻辑自解释。
功能特性
1. 逻辑语义化
and:所有任务必须成功(等价于Promise.all)or:至少一个任务成功(等价于Promise.any)xor:有且仅有一个任务成功nand:不是所有任务都成功(至少一个失败)nor:所有任务都失败(没有任务成功)xnor:所有任务都成功或都失败(状态相同)not:反转单个 Promise 的结果majority:多数任务成功
2. 零依赖
仅依赖原生 Promise,无额外运行时依赖。
3. 全测试覆盖
所有逻辑门均经过严格单元测试,确保行为符合预期。
4. 错误分类明确
PromiseLogicError统一错误类型error.type区分具体逻辑错误(如'XOR_ERROR')- 支持自定义错误类型和消息
5. 超时控制
maxTimer:为任何 Promise 操作添加超时功能(单位:毫秒)- 支持自定义超时错误信息
说明:超时后会立即中断当前 Promise 链的执行,跳转到错误处理,但不会取消已经开始的底层异步操作(如网络请求、文件读写等)。
6. 扩展操作
allFulfilled:按顺序返回所有成功结果,当存在成功结果时会立即尝试返回allRejected:按顺序返回所有失败结果,当存在失败结果时会立即尝试返回allSettled:返回所有结果(包括成功和失败)
安装
npm install promise-logic
快速开始
基础使用示例
安全审计(XOR 场景)
import { PromiseLogic } from 'promise-logic';
// 执行 XOR 逻辑:有且仅有一个成功
PromiseLogic.xor([
biometricAuth(), // 生物识别
hardwareKeyAuth() // 硬件密钥
])
.then((result) => {
console.log('成功获取数据:', result);
})
.catch((error) => {
if (error.type === 'XOR_ERROR') {
console.error('生物识别和硬件密钥发生冲突');
} else {
console.error('网络错误:', error);
}
});
多数决决策(Majority 场景)
import { PromiseLogic } from 'promise-logic';
const services = [
fetch('https://api.node1.com/vote'),
fetch('https://api.node2.com/vote'),
fetch('https://api.node3.com/vote')
];
// 自定义阈值 0.6 (60%)
PromiseLogic.majority(services, { max: 0.6 })
.then((results) => {
console.log('达到自定义阈值,成功结果:', results);
})
.catch((error) => {
console.error('未达到自定义阈值:', error);
});
超时控制
import { PromiseLogic } from 'promise-logic';
// 执行带自定义超时错误信息的操作
PromiseLogic.and([
Promise.resolve(1),
new Promise((resolve) => setTimeout(resolve, 3000)), // 3秒操作
Promise.resolve(3)
])
.maxTimer(2000, '自定义超时错误:操作在 2000ms 内未完成') // 2秒超时
.then((result) => {
console.log('操作在超时时间内完成:', result);
})
.catch((error) => {
console.error('操作超时:', error.message);
});
扩展操作
import { PromiseLogic } from 'promise-logic';
const operations = [
Promise.resolve('success1'),
Promise.reject('error1'),
Promise.resolve('success2'),
Promise.reject('error2')
];
// 获取所有成功结果(一有成功就立即返回)
PromiseLogic.allFulfilled(operations).then((results) => {
console.log('成功结果:', results); // ['success1', 'success2']
});
// 获取所有失败结果(一有失败就立即返回)
PromiseLogic.allRejected(operations).then((errors) => {
console.log('失败结果:', errors); // ['error1', 'error2']
});
// 获取所有结果(包括成功和失败)
PromiseLogic.allSettled(operations).then((results) => {
console.log('所有结果:', results);
});
自定义错误类型和消息
import { PromiseLogic } from 'promise-logic';
// 自定义错误类型
const CUSTOM_ERROR_TYPE = 'CUSTOM_ERROR';
// 自定义错误消息
const CUSTOM_ERROR_MESSAGE = 'Custom error message';
// 使用自定义错误类型和消息
PromiseLogic.and([Promise.resolve('success1'), Promise.reject('error1')], {
errorType: CUSTOM_ERROR_TYPE,
errorMessage: CUSTOM_ERROR_MESSAGE
})
.then((results) => {
console.log(results);
})
.catch((error) => {
if (error.type === CUSTOM_ERROR_TYPE) {
console.error(error); // 输出:Custom error message
} else {
console.error(error);
}
});
使用工厂函数
工厂函数允许你创建自定义命名的 PromiseLogic 方法:
import { createPromiseLogic } from 'promise-logic';
// 创建自定义命名的实例
const logic = createPromiseLogic({
prefix: 'api_',
suffix: '_call',
rename: {
and: 'all',
or: 'any',
xor: 'exclusive'
}
});
// 使用自定义命名的方法
logic.api_all_call([fetch('/api/users'), fetch('/api/posts')]);
logic.api_any_call([fetch('/api/cache'), fetch('/api/database')]);
TypeScript 支持
import { PromiseLogic } from 'promise-logic/typescript';
// 类型推断
PromiseLogic.and([Promise.resolve(1), Promise.resolve(2)]).then(
(results: number[]) => {
console.log(results);
}
);
// 类型断言
PromiseLogic.and<number>([Promise.resolve(1), Promise.resolve(2)]);
动态逻辑嵌套
import { PromiseLogic } from 'promise-logic';
// 动态嵌套示例:根据用户等级调整物流策略
const orderFlow = async (userLevel) => {
// VIP用户:双高可用物流保障(至少一个成功)
// 普通用户:优先标准物流,失败则降级为经济物流(至少一个成功)
const logisticsStrategy = userLevel === 'VIP'
? PromiseLogic.or([premiumLogistics(), backupLogistics()])
: PromiseLogic.or([standardLogistics(), economyLogistics()]);
return await PromiseLogic.and([
PromiseLogic.and([paymentAPI(), inventoryAPI()]), // 支付+库存原子操作
logisticsStrategy, // 物流策略
couponValidation() // 优惠券验证
]);
};
API 参考
| API | 说明 |
|---|---|
and | 所有 Promise 成功,返回结果数组;任一失败则整体失败,等价原生 Promise.all。 |
or | 至少一个 Promise 成功,返回首个成功结果;全部失败则整体失败,等价原生 Promise.any。 |
xor | 有且仅有一个 Promise 成功,返回该结果;否则抛出 XOR_ERROR。 |
nand | 不是所有 Promise 都成功(至少一个失败),返回成功结果数组;全部成功则整体失败。 |
nor | 所有 Promise 都失败(没有任务成功),返回空数组;任一成功则整体失败。 |
xnor | 所有 Promise 都成功或都失败(状态相同),返回成功结果数组;否则抛出 XNOR_ERROR。 |
not | 反转单个 Promise 的结果:成功变失败,失败变成功。 |
majority | 超过指定阈值的 Promise 成功,返回成功结果数组;否则整体失败。接受 options 参数,其中 max 属性可自定义阈值(默认:0.5),范围:[0,1]。 |
allFulfilled | 返回所有成功结果作为数组,忽略失败结果。存在成功结果立即返回,同时保持输入输出顺序一致。 |
allRejected | 返回所有失败结果作为数组,忽略成功结果。存在失败结果立即返回,同时保持输入输出顺序一致。 |
allSettled | 返回所有结果(包括成功和失败)作为数组,等价原生 Promise.allSettled。 |
race | 返回第一个完成的 Promise 结果(无论成功或失败),等价原生 Promise.race。 |
maxTimer | 为任何 Promise 操作添加超时功能(单位:毫秒)。支持自定义超时错误信息。 |
更新日志
v2.9.0
错误机制完善
- 添加逻辑门的
errorType和errorMessage参数,支持自定义错误类型和消息,进一步贴合业务场景 - 优化现有的错误类型体系,确保 TypeScript 类型定义正确
- 优化 TypeScript 类型兼容问题
- 优化 allSettled 门的返回类型错误信息
- 完善测试脚本,覆盖大部分了 promise 组合逻辑边界和刁钻的场景问题,确保逻辑门的运行更加稳定
- 优化了逻辑门的执行效率,减少了不必要的 Promise 包装
v2.8.0
- 从底层优化
allFulfilled和allRejected实现逻辑,存在结果便立即返回,同时保持输入和输出顺序一致 - 新增链式超时控制自定义错误信息:可以在
maxTimer方法中自定义超时错误信息 - 类型修复:修复 TypeScript 版本的类型声明问题
- 测试完善:添加
allFulfilled、allRejected和maxTimer完整测试用例 - 代码重构:改进代码结构,提高可维护性
贡献指南
1. 开发环境
git clone https://github.com/xier123456/promise-logic.git
cd promise-logic
npm install
2. 测试
npm test
3. 提交规范
- 提交信息需包含
feat:(新功能)、fix:(修复)、docs:(文档)前缀。 - Pull Request 需附带测试用例。
资源链接
- GitHub 仓库:github.com/xier123456/…
- npm 包:www.npmjs.com/package/pro…
- Issue 跟踪:GitHub Issues