【问题标题】:Promise.all returning Promise, not the expected data payload in .next(...)Promise.all 返回 Promise,而不是 .next(...) 中的预期数据负载
【发布时间】:2020-09-06 16:05:45
【问题描述】:

我目前正在尝试理解 Promise 和 Promise all。我有一个我想在这里实现的实现,几乎可以工作:

https://codepen.io/c0un7z3r0/pen/GRpPyar

代码是:

const currencyArray = [
  {
    currencyFrom: "USD",
    currencyTo: "GBP",
    urls:[
      "https://jsonplaceholder.typicode.com/todos/1",
      "https://jsonplaceholder.typicode.com/todos/2",
    ]
  },
  {
    currencyFrom: "SGD",
    currencyTo: "USD",
    urls:[
      "https://jsonplaceholder.typicode.com/todos/3",
      "https://jsonplaceholder.typicode.com/todos/4",
    ]
  },
  {
    currencyFrom: "CNY",
    currencyTo: "EUR",
    urls:[
      "https://jsonplaceholder.typicode.com/todos/5",
      "https://jsonplaceholder.typicode.com/todos/6",
    ]
  }
]

async function fetchData(currencyFrom, currencyTo, url) {
  const res = await fetch(url)
  let dataResp = await res.json()
  dataResp = dataResp.map((data) => data)
  let newDataObj = {
    currencyFrom: currencyFrom,
    currencyTo: currencyTo,
    response: dataResp,
  }
  return newDataObj
}

const promises = currencyArray.map((currency) =>
                                   currency.urls.map((url) => {
  return fetchData(currency.currencyFrom, currency.currencyTo, url).then(
    (data) => {
      // console.log(data)
      return data
    })
  })
)

Promise.all(promises)
  .then((data) => data)
  .then((data) => console.log('I expect data, but all I get is Promises, Promises:', data))

我想要实现的是通过currencyArray 中的每个对象进行映射,从currencyArray.url 数组中的每个url 获取数据,然后在所有promise 都已解决时为每个currencyArray 项返回一个类似的对象,例如所以:

[{
    currencyFrom: "USD",
    currencyTo: "GBP",
    responses:[
        // ** DATA FETCHED FROM API CALLS **
    ]

},{
    // ....more objects like the above
}
]

上面的 codepen 实现已经完成了 99%,但是无论我做什么,结果总是返回 [Promise, Promise] 数组。如果我在浏览器控制台中深入研究数组,我实际上可以看到解析的数据,但是尝试在 .then() 中访问此信息已被证明是徒劳的。任何人都可以帮助我理解我做错了什么并可能提供一个可行的例子吗?

我已经搜索了堆栈溢出并尝试了许多替代实现,以上是我管理的最接近工作解决方案的解决方案。 提前感谢您提供的任何帮助。

注意:为了完整起见,这里是我在我的应用程序 (https://codepen.io/c0un7z3r0/pen/ExVGQdK) 中的实际实现,上面的代码笔是修改为使用公共 API 的版本。

【问题讨论】:

    标签: javascript arrays promise async-await


    【解决方案1】:

    问题似乎不在于承诺本身,而在于构建数组的方式。内部映射创建了一个内部承诺集合,但外部映射不直接使用这些承诺。 flatMap 可用于展平集合:

    const promises = currencyArray.flatMap(currency =>
      currency.urls.map(url => fetchData(currency.currencyFrom, currency.currencyTo, url))
      );
    

    const currencyArray = [
      {
        currencyFrom: "USD",
        currencyTo: "GBP",
        urls:[
          "https://jsonplaceholder.typicode.com/todos/1",
          "https://jsonplaceholder.typicode.com/todos/2",
        ]
      },
      {
        currencyFrom: "SGD",
        currencyTo: "USD",
        urls:[
          "https://jsonplaceholder.typicode.com/todos/3",
          "https://jsonplaceholder.typicode.com/todos/4",
        ]
      },
      {
        currencyFrom: "CNY",
        currencyTo: "EUR",
        urls:[
          "https://jsonplaceholder.typicode.com/todos/5",
          "https://jsonplaceholder.typicode.com/todos/6",
        ]
      }
    ]
    
    async function fetchData(currencyFrom, currencyTo, url) {
      const res = await fetch(url),
        dataResp = await res.json(),
        newDataObj = {
        currencyFrom: currencyFrom,
        currencyTo: currencyTo,
        response: dataResp,
      };
      return newDataObj
    }
    
    const promises = currencyArray.flatMap(currency =>
      currency.urls.map(url => fetchData(currency.currencyFrom, currency.currencyTo, url))
      );
    
    Promise.all(promises).then(console.log);

    【讨论】:

    • 太棒了!感谢您指出问题所在并提供解决方案!我以前从未听说过或见过使用过的“flatMap”。我现在要调查差异!再次感谢!
    • 控制台使用 'map' 和 'flatMap' 注销我的 promises 变量显示了两组不同的 promises - 但我真的不明白它的区别,你能不能扩展一下它是如何工作的?
    • 很高兴它有帮助。 flatMap 本身相对较新。相当于 C# 中的 SelectMany。第一个 map(map) 构造在数组[[1,2][3,4]] 中创建了一个数组flatMap 所做的是将它“展平”,即:它从所有内部数组/可迭代对象中创建一个数组:[1,2,3,4]。跨度>
    • 太棒了,这也解释了我在控制台中看到的内容。一百万年来,我不会尝试将“flatMap”作为解决方案。非常感谢你的帮助。我已经在这个问题上待了 2 天,很高兴解决了这个问题 - 没有你的帮助我做不到。再次感谢。
    【解决方案2】:

    Promise.all 在您有一系列承诺 [Promise, Promise, ...] 时有效。在您的情况下,这是一组 Promises [[Promise, Promise], ...]

    这就是我合并所有这些值的方式

    const promises = [
      [
        new Promise((resolve, reject) => resolve({prop:1})),
        new Promise((resolve, reject) => resolve({prop:2}))
      ],
      [
        new Promise((resolve, reject) => resolve({prop:3})),
        new Promise((resolve, reject) => resolve({prop:4}))
      ],
      [
        new Promise((resolve, reject) => resolve({prop:5})),
        new Promise((resolve, reject) => resolve({prop:6}))
      ]
    ];
    
    (async() => {
      const result = await Promise.all(promises.map(async pr => await Promise.all(pr)))
      console.log(result);
    })()

    【讨论】:

      猜你喜欢
      • 2018-11-03
      • 2021-03-17
      • 2020-08-06
      • 2018-05-16
      • 2017-05-04
      • 2017-10-31
      • 2020-12-08
      • 2017-06-02
      • 2021-02-06
      相关资源
      最近更新 更多