Javascript 在React-Redux中嵌套API调用
我很难弄清楚在我的动作创造者身上发生了什么(和没有发生什么) 我需要对一个API端点进行调用,获取返回的所有项的ID和名称,然后对每个ID进行另一个调用。我想将最后一次调用的返回和第一次调用的ID/名称存储在一个对象中,并分派它Javascript 在React-Redux中嵌套API调用,javascript,reactjs,redux,react-redux,Javascript,Reactjs,Redux,React Redux,我很难弄清楚在我的动作创造者身上发生了什么(和没有发生什么) 我需要对一个API端点进行调用,获取返回的所有项的ID和名称,然后对每个ID进行另一个调用。我想将最后一次调用的返回和第一次调用的ID/名称存储在一个对象中,并分派它 { category: name //name of category subcategory: [] //array of categories in the category above. } 现在,我的reducer确实得到了我想要的东西,但是当我尝试
{
category: name //name of category
subcategory: [] //array of categories in the category above.
}
现在,我的reducer确实得到了我想要的东西,但是当我尝试在组件中记录特定的道具时,它是空的。(下面我使用的是OpenSocialAPI或osapi。这只是ajax请求的基本包装。允许我不必进行身份验证,因为它认为我已经通过了身份验证。)
在我的应用程序中,我在componentDidMount中调度动作创建者
componentDidMount() {
const { dispatch } = this.props
dispatch(fetchCategoriesIfNeeded(id))
}
现在,当我登录到我的分类组件和上面的execute中时,它是空的。但是看看我在记录器中的状态,当ReceiveCategories完成时,我就有了我想要的对象数组
[{category:...,
subcategories:[...]
},
{category:...,
subcategories:[...]
}]
我怀疑这是因为异步的原因,但我不确定如何继续
我试图为基于承诺的调用创建自己的包装器,但我遇到了类似的问题,可能更严重,因为我不确定解决(响应)是否是我想要的
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响应构建的数组是一种有效的方法,还是有更好的方法?多谢各位
我只能找到另外一个类似用例的问题,但他们使用的是蓝鸟或类似的东西。我真的很想保留这个,除了Redux之外没有任何额外的东西 看起来您只需要在
.execute()
回调中分派类别,而不是在回调之外。您正在执行osapi.core.get()
您还需要使用Promise.all
来获取所有嵌套get
请求的响应
也没有理由保留一个变异数组。我猜osapi.core.get
是一种基于承诺的获取库,并且在获取成功时调用
如果是这样,那么您缺少的是没有等待所有异步调用完成
我将展示一个基于泛型fetch
和本机承诺的解决方案,这样您就可以理解该解决方案,并根据您的特定库采用它
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))
});
此外,您在嵌套函数中使用了相同的变量-虽然这可能会起作用,计算机可能会理解它,但这使得任何人都很难确定哪个响应属于哪个范围。因此,您可能还想再看一看您的变量名。您使用的是redux thunk,对吗?是的,我使用的是redux thunk。我的道具映射正确,因为我正在修改一个动作,该动作以前只查看一层类别,现在需要更深入地查看。您正在使用的这个获取库是什么?如果不查看.execute()的内容,很难为正确的修复编写代码
API is..execute只是osapi的.then。如果可能的话,你应该切换到redux sagaInteresting。让另一组眼睛看事情总是很好的。我在最外层执行调度。因为它在循环中,调度自然运行第一个响应的长度。我能简单地将Promise.all包装在secon周围吗d osapi.core.get()?另外,您提到没有保留一个变异数组,您是指类别数组?您建议在末尾删除它吗?或者用另一种方法来构建缩减器数组,而不是定义一个?Promise.all接受一个Promise数组,并行运行它们,并返回一个包含所有值的数组。您不需要使用forEach
andpush
,只需将最终结果作为map
返回到所需的数据结构即可。谢谢!我将查看并尝试一下。从execute()api很难判断,您可能需要“promisify”它以使其与promise配合良好。所有这些,就像制作一个正确调用resolve()或reject()的promise包装器一样遵循标准的promise api,不是一个国产的promise api能够用promise实现这一点。所有!学习起来很有趣!我必须使用数组变量来存储承诺。谢谢!是的,当它成功时调用execute。谢谢你写出来!我会看看这个和promise。所有提到的。另外,我更改了所以,就因为他们很敏感,谢谢你让我保持诚实!我会在一点时间后汇报事情的进展。酷!如果答案对你有帮助,别忘了投票。
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))
});