UNPKG

@flowlab/all

Version:

A cool library focusing on handling various flows

148 lines (132 loc) 6.47 kB
// ---------- 模拟的外部服务 ---------- interface UserInfo { userId: string; email: string; vipLevel: 'VIP' | 'Normal'; } interface ProductInfo { productId: string; price: number; stock: number; } interface Order { orderId: string; userId: string; productId: string; finalPrice: number; status: 'Created' | 'Failed'; } // 模拟用户服务 (可能失败) async function fetchUserService(userId: string): Promise<UserInfo> { console.log(`[服务] 获取用户 ${userId} 信息...`); await new Promise(res => setTimeout(res, 50)); // 模拟网络延迟 if (Math.random() < 0.1) { // 10% 概率失败 throw new Error('用户服务暂时不可用'); } return { userId, email: `${userId}@test.com`, vipLevel: Math.random() > 0.5 ? 'VIP' : 'Normal' }; } // 模拟商品服务 (可能失败) async function fetchProductService(productId: string): Promise<ProductInfo> { console.log(`[服务] 获取商品 ${productId} 信息...`); await new Promise(res => setTimeout(res, 60)); // 模拟网络延迟 if (Math.random() < 0.1) { // 10% 概率失败 throw new Error('商品服务暂时不可用'); } const stock = Math.floor(Math.random() * 5); // 0-4 的随机库存 return { productId, price: 100, stock }; } // 模拟订单服务 (可能失败) async function createOrderService(userId: string, productId: string, price: number): Promise<{ orderId: string }> { console.log(`[服务] 正在为用户 ${userId} 创建商品 ${productId} 的订单,价格: ${price}...`); await new Promise(res => setTimeout(res, 70)); if (Math.random() < 0.05) { // 5% 概率失败 throw new Error('订单服务创建失败'); } return { orderId: `order-${Date.now()}` }; } // 模拟邮件服务 async function sendEmailService(email: string, subject: string, body: string): Promise<void> { console.log(`[服务] 发送邮件给 ${email} | 主题: ${subject} | 内容: ${body}`); await new Promise(res => setTimeout(res, 40)); // 假设邮件发送总能成功 } // ---------- 带重试的辅助函数 ---------- async function retry<T>(fn: () => Promise<T>, retries = 2, delayMs = 100): Promise<T> { let lastError: Error | undefined; for (let i = 0; i <= retries; i++) { try { return await fn(); // 尝试执行 } catch (error: any) { lastError = error; // 记录错误 console.warn(`[重试] 第 ${i + 1} 次尝试失败: ${error.message}`); if (i < retries) { await new Promise(res => setTimeout(res, delayMs * Math.pow(2, i))); // 指数退避等待 } } } console.error(`[重试] 达到最大重试次数后仍然失败。`); throw lastError; // 抛出最后一次的错误 } // ---------- 主要业务流程函数 ---------- async function processOrderRequest(request: { userId: string; productId: string }) { console.log(`\n--- 开始处理订单请求: 用户 ${request.userId}, 商品 ${request.productId} ---`); let userInfo: UserInfo | undefined; let productInfo: ProductInfo | undefined; let finalPrice = 0; let orderResult: { orderId: string } | undefined; let orderStatus: 'Success' | 'Failed' = 'Failed'; // 默认失败 let failureReason = ''; try { // 1 & 2: 并行获取用户信息和商品信息 (带重试) // 注意:实际项目中可能需要更健壮的并行控制和错误处理库 (如 Promise.allSettled) [userInfo, productInfo] = await Promise.all([ retry(() => fetchUserService(request.userId)), retry(() => fetchProductService(request.productId)) ]); console.log('[流程] 用户和商品信息获取成功。'); // 3. 检查库存 if (productInfo.stock <= 0) { failureReason = '商品库存不足'; console.warn(`[流程] ${failureReason}`); throw new Error(failureReason); // 中断流程 } console.log(`[流程] 库存检查通过 (${productInfo.stock})。`); // 4. 计算价格 finalPrice = productInfo.price; if (userInfo.vipLevel === 'VIP') { finalPrice = finalPrice * 0.9; // VIP 九折 console.log(`[流程] 用户是 VIP,应用折扣。最终价格: ${finalPrice}`); } else { console.log(`[流程] 用户非 VIP。最终价格: ${finalPrice}`); } // 5. 创建订单 (带重试) orderResult = await retry(() => createOrderService(userInfo!.userId, productInfo!.productId, finalPrice), 1, 200); // 重试1次 orderStatus = 'Success'; console.log(`[流程] 订单创建成功: ${orderResult.orderId}`); } catch (error: any) { console.error(`[流程] 处理订单时发生错误: ${error.message}`); if (!failureReason) { // 如果没有指定具体业务失败原因,则使用捕获到的错误 failureReason = error.message; } // 即使失败,也需要尝试发送通知,所以错误在这里被捕获 } // 6. 发送通知 (无论成功失败都尝试发送) if (userInfo) { // 只有获取到用户信息才能发送邮件 const subject = orderStatus === 'Success' ? '订单创建成功' : '订单创建失败'; const body = orderStatus === 'Success' ? `您的订单 ${orderResult?.orderId} 已成功创建,商品 ${request.productId},价格 ${finalPrice}。` : `抱歉,您的订单 (商品 ${request.productId}) 创建失败。原因: ${failureReason}`; try { await sendEmailService(userInfo.email, subject, body); console.log('[流程] 通知邮件已发送。'); } catch (emailError: any) { console.error(`[流程] 发送通知邮件失败: ${emailError.message}`); // 记录发送邮件失败,但通常不影响主流程结果 } } else { console.warn('[流程] 未能获取用户信息,无法发送通知邮件。'); } console.log(`--- 订单请求处理结束,最终状态: ${orderStatus} ---`); // 返回一个包含最终状态和相关信息的结果对象 return { success: orderStatus === 'Success', orderId: orderResult?.orderId, userId: request.userId, productId: request.productId, finalPrice: orderStatus === 'Success' ? finalPrice : undefined, reason: orderStatus !== 'Success' ? failureReason : undefined, }; } // ---------- 执行示例 ---------- async function runExample() { await processOrderRequest({ userId: 'user1', productId: 'productA' }); // 可以再调用几次,观察随机失败和库存不足的情况 // await processOrderRequest({ userId: 'user2', productId: 'productB' }); } runExample();