嵌套 Promise 的变量分配未解决Stripe API

问题描述

使用 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))
}