问题描述
使用 Stripe API,我调用所有产品 stripe.products.list()
,然后尝试使用 stripe.prices.list()
函数为每个产品附加定价数据 map()
。每个调用都会返回一个承诺,尽管嵌套的承诺没有解析,而是返回一个空的 prices 对象。我错过了什么?
export function handler(event,context,callback) {
stripe.products
.list()
.then(products =>
products.data.map(product => ({
...product,prices: stripe.prices // <-- ASSIGNMENT NOT RESOLVED
.list({ product: product.id })
.then(prices => {
console.log(prices) // <-- RESOLVED IN CONSOLE
return prices
}),}))
)
.then(rsp => {
callback(null,{
headers: { 'Content-Type': 'application/json' },statusCode: 200,body: JSON.stringify(rsp),})
})
.catch(err => console.warn(err))
}
解决方法
Array.map
是同步执行的,您无需等待 products.data.map
内的承诺。 prices
对象不是空的,它是一个承诺。控制台中的输出仅在处理程序返回后生成。
一种简单的方法,如下所示。即将收到的产品存储在一个变量中。然后使用 Promise.all()
获取所有产品的价格。然后组合这两个数组以获得最终结果。
export function handler(event,context,callback) {
let theproducts;
stripe.products
.list()
.then(products => {
theproducts = products.map(p => p.data);
return Promise.all(products.data.map(product =>
stripe.prices.list({ product: product.id }))
)
})
.then(prices => theproducts.map((p,i) => ({...p,prices: prices[i]})
.then(rsp => {
callback(null,{
headers: { 'Content-Type': 'application/json' },statusCode: 200,body: JSON.stringify(rsp),})
})
.catch(err => console.warn(err))
}
您还可以在 stripe.prices.list()
解析时立即合并产品和价格,从而节省地图的额外迭代。但我个人觉得这样更易读。如果您没有太多产品,额外的迭代不会花费太长时间。
您不是在等待内部承诺解决:
export function handler(event,callback) {
stripe.products
.list()
.then(products =>
return Promise.all(products.data.map(product => {
return stripe.prices // <-- ASSIGNMENT NOT RESOLVED
.list({ product: product.id })
.then(prices => {
console.log(prices) // <-- RESOLVED IN CONSOLE
return prices
}),}))
.then(prices => {
return {
...product,prices
};
});
)
.then(rsp => {
callback(null,{
headers: { 'Content-Type': 'application/json' },})
})
.catch(err => console.warn(err))
}
,
您已返回 products.data.map 中的数组。然而,这是一系列的承诺。当您映射它们并链接承诺时。它实际上并没有解决承诺。我建议你尝试一些异步语法来简化代码。
(async () => {
const blah = products.data.map(product => {
const prices = await stripe.prices.list({ product: product.id });
return { ...product,prices };
});
console.log(blah);
})()
,
通过大量有用的输入,我最终得到了以下内容。
export function handler(event,callback) {
stripe.products
.list()
.then(products => {
return Promise.all(
products.data.map(product =>
stripe.prices
.list({ product: product.id })
.then(prices => {
return prices
})
.then(prices => {
return {
...product,prices,}
})
)
)
})
.then(rsp => {
callback(null,})
})
.catch(err => console.warn(err))
}