Stripe订单金额计算函数异步问题:返回早于Map执行完成
问题原因
map与await不兼容:items.map(async () => {})会返回一个由Promise组成的数组,但await只能等待单个Promise完成,无法直接等待整个Promise数组。因此await items.map(...)不会等待所有异步查询完成,就直接执行后续的console.log和return语句,导致总价计算不完整。- 缺少
await调用异步计算函数:在create-payment-intent接口中,调用calculateOrderAmount(items)和calculateAmount(items)时没有添加await,导致传入Stripe的是Promise对象而非实际计算出的金额数值,这不仅会导致金额错误,还可能引发Stripe API调用失败。
解决方案
1. 使用Promise.all等待所有异步操作完成
将map生成的Promise数组传入Promise.all,通过await等待所有商品价格查询完成后再进行总价累加。也可以结合reduce更优雅地处理累加逻辑,避免使用外部变量。
2. 在调用异步计算函数时添加await
确保create-payment-intent中传入Stripe的是实际计算出的金额数值,而非Promise对象。
修改后的代码
const express = require('express') const mongoose = require('mongoose') const stripe = require("stripe")(process.env.STRIPE_TEST_KEY); const cors = require('cors') const path = require("path"); const userRoutes = require('./routes/user') const productRoutes = require('./routes/product') const orderRouts = require('./routes/order') const Product = require('./models/productModel') require('dotenv').config() const app = express() app.use(cors()) app.use(express.json()) app.use(express.urlencoded({ extended: false })); app.use("/images", express.static(path.join(__dirname, "images"))); app.use('/product', productRoutes) app.use('/user', userRoutes) app.use('/orders', orderRouts) const calculateAmount = async (items) => { const _id = items[0].id console.log(_id) const product = await Product.findById({ _id }) const price = items[0].amount * product.price console.log(price) return price * 100; }; const calculateOrderAmount = async (items) => { // 使用Promise.all等待所有商品价格查询完成 const itemPrices = await Promise.all( items.map(async (item) => { const product = await Product.findById(item.id); return item.amount * product.price; }) ); // 累加所有商品的总价 const totalPrice = itemPrices.reduce((sum, price) => sum + price, 0); console.log(`total price is ${totalPrice}`) return totalPrice; }; app.post('/create-payment-intent', async (req, res) => { const { items } = req.body; console.log(items) // 调用计算函数时添加await,确保拿到实际金额 const amount = items.length > 1 ? await calculateOrderAmount(items) : await calculateAmount(items); const paymentIntent = await stripe.paymentIntents.create({ amount: amount * 100, // 统一转换为最小货币单位(分) currency: "cad", automatic_payment_methods: { enabled: true }, }); res.status(200).send({ clientSecret: paymentIntent.client_secret }) }) mongoose.set("strictQuery", false) mongoose.connect(process.env.MONGO_URL) .then(() => { app.listen(process.env.PORT, () => { console.log('listening on port', process.env.PORT) }) }) .catch((error) => { console.log(error) })
额外说明
Promise.all会并行执行所有异步查询,相比逐个等待(比如for...of循环)效率更高,适合无依赖的异步操作。- 使用
reduce累加总价避免了外部变量的修改,代码更简洁且符合函数式编程风格。 - 统一将金额乘以100转换为最小货币单位(分),符合Stripe API的参数要求,保持逻辑一致性。
内容的提问来源于stack exchange,提问作者Mohammed Abdo
相关产品推荐
相关产品推荐

