gpt4 book ai didi

javascript - 嵌套异步 - 最佳实践

转载 作者:行者123 更新时间:2023-11-28 16:45:22 25 4
gpt4 key购买 nike

我正在制作虚拟应用程序来测试服务器端 API。第一个请求返回嵌套的 JSON 对象,其中包含产品名称及其所具有的变体数量。从那里我提取产品名称,以便我可以发送第二个请求来获取包含产品图像、尺寸等的变体列表。

first request

second request

有时它只会加载和显示一种产品的变体,但大多数时候它会正常工作并加载两个虚拟产品的所有变体。有没有更好的方法来确保它始终如一地正常工作。我也想知道是否有更好的整体方法来编写这样的东西。

代码如下:

  import React, { useEffect, useState } from "react";
import axios from "axios";

import ShirtList from "../components/ShirtList";

const recipeId = "15f09b5f-7a5c-458e-9c41-f09d6485940e";

const HomePage = props => {
const [loaded, setLoaded] = useState(false);

useEffect(() => {
axios
.get(
`https://api.print.io/api/v/5/source/api/prpproducts/?recipeid=${recipeId}&page=1`
)
.then(response => {
let shirtList = [];
const itemsLength = response.data.Products.length;
response.data.Products.forEach((element, index) => {
axios
.get(
`https://api.print.io/api/v/5/source/api/prpvariants/?recipeid=${recipeId}&page=1&productName=${element.ProductName}`
)
.then(response => {
shirtList.push(response.data.Variants);
if (index === itemsLength - 1) {
setLoaded(shirtList);
}
});
});
});
}, []);

const ListItems = props => {
if (props.loaded) {
return loaded.map(item => <ShirtList items={item} />);
} else {
return null;
}
};

return (
<div>
<ListItems loaded={loaded} />
</div>
);
};

export default HomePage;

最佳答案

您在每次迭代后设置加载的衬衫,因此您只会获得最后解析的 promise 数据,而不是获取所有数据,然后更新状态。

此外,将您的状态分开,一个用于加载状态,一个用于数据。

选项 1 使用async/await

const recipeId = '15f09b5f-7a5c-458e-9c41-f09d6485940e'
const BASE_URL = 'https://api.print.io/api/v/5/source/api'

const fetchProducts = async () => {
const { data } = await axios.get(`${BASE_URL}/prpproducts/?recipeid=${recipeId}&page=1`)
return data.Products
}

const fetchShirts = async productName => {
const { data } = await axios.get(
`${BASE_URL}/prpvariants/?recipeid=${recipeId}&page=1&productName=${productName}`,
)
return data.Variants
}

const HomePage = props => {
const [isLoading, setIsLoading] = useState(false)
const [shirtList, setShirtList] = useState([])

useEffect(() => {
setIsLoading(true)

const fetchProductShirts = async () => {
const products = await fetchProducts()
const shirts = await Promise.all(
products.map(({ productName }) => fetchShirts(productName)),
)
setShirtList(shirts)
setIsLoading(false)
}

fetchProductShirts().catch(console.log)
}, [])
}

使用原始 promise 的选项 2

const recipeId = '15f09b5f-7a5c-458e-9c41-f09d6485940e'
const BASE_URL = 'https://api.print.io/api/v/5/source/api'

const fetchProducts = () =>
axios.get(`${BASE_URL}/prpproducts/?recipeid=${recipeId}&page=1`)
.then(({ data }) => data.Products)


const fetchShirts = productName =>
axios
.get(
`${BASE_URL}/prpvariants/?recipeid=${recipeId}&page=1&productName=${productName}`,
)
.then(({ data }) => data.Variants)

const HomePage = props => {
const [isLoading, setIsLoading] = useState(false)
const [shirtList, setShirtList] = useState([])

useEffect(() => {
setIsLoading(true)

fetchProducts
.then(products) =>
Promise.all(products.map(({ productName }) => fetchShirts(productName))),
)
.then(setShirtList)
.catch(console.log)
.finally(() => setIsLoading(false)
}, [])
}

现在您有用于加载状态的 isLoading 状态和用于数据的 shirtList 状态,您可以基于此进行渲染

return (
<div>
{isLoading ? (
<span>loading...</span>
) : (
// always set a unique key when rendering a list.
// also rethink the prop names
shirtList.map(shirt => <ShirtList key={shirt.id} items={shirt} />)
)}
</div>
)

引用文献

Promise.all

Promise.prototype.finally

React key prop

关于javascript - 嵌套异步 - 最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60615309/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com