【问题标题】:Resolve a promise / perform an asynchronous operation inside of .map()在 .map() 中解决承诺/执行异步操作
【发布时间】:2021-07-20 07:35:05
【问题描述】:

我一直在学习 React,并且玩得很开心。为了练习使用钩子和上下文 API,我创建了一个非常简单的 Pokemon 应用程序,它从(非常棒的)PokéAPI 获取数据。我似乎无法解决的问题是如何通过从第一次获取数据中检索到的 url 获取数据来初始化我的上下文。这当然是一个糟糕的解释,但我下面的代码澄清了。

我已经将 <App /> 组件包装在 <ContextProvider /> 中,如下所示:

import React from 'react'
import ReactDOM from 'react-dom'

import App from './App';
import { ContextProvider } from './Context'

ReactDOM.render(
    <ContextProvider>
        <App />    
    </ContextProvider>, 
    document.getElementById('root')
);

然后直接跳转到我的 Context.js 文件,我正在获取应用程序首次加载时所需的数据:

import React, { useState, useEffect } from 'react'
import fetchSprite from './utils/fetchSprite'
const Context = React.createContext()

function ContextProvider({ children }) {
    const [ allPokemon, setPokemon ] = useState([])
    console.log(allPokemon)

    useEffect(() => {
        const fetchData = async () => {
            const response = await fetch("https://pokeapi.co/api/v2/pokemon?limit=25")
            const pokemon = await response.json()
            
            /* Do ANOTHER async operation here */

            ))
            setPokemon(pokemon.results)
        }
        fetchData()
    }, [])

    return (
        <Context.Provider value={{ allPokemon }}>
            {children}
        </Context.Provider>
    )
}

export { ContextProvider, Context }

解析作为响应提供的 JSON 后,pokemon.results 是一个对象数组,其中每个对象包含一个 nameurl 属性。 我正在尝试对每个对象使用 url 进行额外的 fetch 调用,这样我还可以存储一个包含指向 PNG 图像的链接的字符串。 同样,在代码中显示这一点将使更有意义:

import React, { useState, useEffect } from 'react'
import fetchSprite from './utils/fetchSprite'
const Context = React.createContext()

function ContextProvider({ children }) {
    const [ allPokemon, setPokemon ] = useState([])

    useEffect(() => {
        const fetchData = async () => {
            const response = await fetch("https://pokeapi.co/api/v2/pokemon?limit=25")
            const pokemon = await response.json()
            const pokeData = pokemon.results.map(obj => (
                {
                    ...obj,
                    sprite: fetchSprite(obj.url)
                }
            ))
            setPokemon(pokeData)
        }
        fetchData()
    }, [])

    return (
        <Context.Provider value={{allPokemon}}>
            {children}
        </Context.Provider>
    )
}

export { ContextProvider, Context }

上面,我采用了我将传递给setPokemon 的相同数组,并且基本上复制了数组,但数组中的每个对象都有一个附加属性sprite

我的fetchSprite.js 文件如下所示:

async function fetchSprite(url) {
    const res = await fetch(url)
    const data = await res.json()
    const result = data.sprites.front_default
    return result
}

export default fetchSprite

我不知道如何解决我的 fetchSprite 函数 inside 在我对 .map() 的调用中返回的 Promise。当数组记录到控制台时,我有一个履行的承诺,但不知道如何访问结果:

Screenshot of array with fulfilled promises, logged to the console

我怎样才能让我的.map() 函数在返回添加到数组的对象之前等待每个承诺解决?我尝试了所有类型的异步组合,例如将 .map() 内部的匿名函数设为异步函数,并将 await 用于 sprite 属性。 UI 中产生的问题是我读取 PNG url 的 img 标签已损坏。这让我很生气——非常感谢任何和所有的帮助!!!

【问题讨论】:

  • const pokeData = await Promise.all(pokemon.results.map(....))
  • 我仍然得到一个对象数组,其中每个对象的sprite 属性是Promise {&lt;fulfilled&gt;: "...somePokemon.png"} :(
  • 嘘!!!使用await Promise.all(...) 并在map 中创建我的匿名函数@ 异步函数有效。谢谢!
  • 您可能想post your solution as an answer,而不是作为问题的编辑。

标签: javascript reactjs promise fetch react-context


【解决方案1】:

感谢see sharper 将我指向Using async/await with a forEach loop

整个map操作应该包裹在await Promise.all()中,并且map里面的匿名函数应该是async函数:

    useEffect(() => {
        const fetchData = async () => {
            const response = await fetch("https://pokeapi.co/api/v2/pokemon?limit=25")
            const pokemon = await response.json()
            const pokeData = await Promise.all(pokemon.results.map(async (obj) => {
                return {
                    ...obj,
                    sprite: await fetchSprite(obj.url)
                }
            }))
            setPokemon(pokeData)
        }
        fetchData()
    }, [])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-20
    • 2021-08-12
    • 2016-01-10
    • 2015-12-08
    • 2019-03-19
    • 1970-01-01
    • 2016-12-06
    相关资源
    最近更新 更多