我很难弄清动作创建者中正在发生(而不是未发生)的情况。
我需要调用一个API端点,获取返回的所有项目的ID和名称,然后针对每个ID进行另一个调用。我想将上次调用的返回值和第一次调用的ID /名称存储在一个对象中并进行分派。
{
category: name //name of category
subcategory: [] //array of categories in the category above.
}
现在,我的减速器确实可以满足我的需求,但是当我尝试在组件中记录该特定道具时,它是空的。 (下面我正在使用OpenSocialAPI或osapi。这只是一个ajax请求的基本包装。它使我不必进行身份验证,因为它看到我已被身份验证。)
export function fetchCategories(id){
let categories = []
return function(dispatch){
dispatch(requestCategories(id))
return osapi.core.get({
v: "v3",
href: "/places/" + id + "/places"
}).execute(function(response) {
response.content.list.forEach(function(category) {
osapi.core.get({
v: "v3",
href: "/places/" + category.id+ "/categories"
}).execute(function(response) {
categories.push({
category: category.name,
subcategories: response.content.list.map(category => category.name)
})
})
})
console.log("Category response: ", categories)
dispatch(receiveCategories(id, categories))
})
}
}
export function receiveCategories(id,array){
return {
type: RECEIVE_CATEGORIES,
id,
categories: array,
recievedAt: new Date(Date.now()),
isFetching: false
}
}
然后在我的应用中,我在componentDidMount中调度动作创建者
componentDidMount() {
const { dispatch } = this.props
dispatch(fetchCategoriesIfNeeded(id))
}
现在,当我在我的Category组件和上面的execute中进行控制台登录时,它为空。但是在记录器中查看状态时,recipeCategories完成后,便有了所需的对象数组
[{category:...,
subcategories:[...]
},
{category:...,
subcategories:[...]
}]
我怀疑这是由于异步原因引起的,但我不确定如何进行。
我试图为基于promise的呼叫创建自己的包装器,但是我遇到了类似的问题,可能还有更多类似的问题,因为我不确定是否要使用resolve(response)。
function httpService(path){
return new Promise(function(resolve, reject){
osapi.core.get({
v: 'v3',
href: path
}).execute(function(response, error){
if(error){
return reject(new Error("Error: ", error))
}
resolve(response)
})
})
}
export function fetchCategories(spaceId) {
let categories = []
return function(dispatch) {
dispatch(requestCategories(id))
return httpService("/places/" + id + "/places")
.then(function(response) {
response.content.list.forEach(function(category) {
fetchSubCategories("/places/" + category.id + "/categories")
.then(function(response) {
categories.push({
category: category.name,
subcategories: response
})
})
})
console.log("CATEGORIES: ", categories)
dispatch(receiveCategories(id, categories))
})
}
}
function fetchSubCategories(url){
return httpService(url)
.then(function(response){
return response.content.list.map(category => category.name)
})
}
您可以看一下并提供指导吗?另外,我是否调度基于API响应构建的数组是一种有效的处理方式,还是有更好的方法?谢谢
我只能用相似的用例找到另外一个问题,但是他们使用的是bluebird或类似的东西。我真的很想保留这个,除了Redux。
答案 0 :(得分:1)
看起来您只需要在.execute()
回调的内部 而不是外部分配类别。您正在执行osapi.core.get().execute((response) =>
,但随后在该execute
回调的外部中,调度了receiveCategories
,该操作将在Promise解决之前很长时间执行,然后调度空数组您进行初始化。
您还需要使用Promise.all
来获取所有嵌套GET
请求的响应。
也没有理由保留变异数组。
答案 1 :(得分:1)
我猜osapi.core.get
是某种基于诺言的提取库?而.execute
会在获取成功时被调用吗?
如果是这样,那么您所缺少的就是您没有等待所有异步调用完成。
我将展示基于通用fetch
和本机Promises的解决方案,以便您了解该解决方案并根据您的特定库采用它。
const promises = [];
response.content.list.forEach(function(category) {
const promise = fetch("/places/" + category.id+ "/categories");
promises.push(promise);
})
Promise.all(promises).then(responses => {
categories = responses.map(response => ({/* do your object mapping here */}))
// now you can dispatch with all received categories
dispatch(receiveCategories(id, categories))
});
此外,您在嵌套函数中使用了相同的变量-尽管这可以工作并且计算机可以理解它,但对于任何人来说,弄清楚哪个response
属于哪个范围都非常困难。因此,您可能还想再看看一下变量名。