Ste*_*n R 5 javascript synchronous promise reactjs
我对 ReactJS 和 redux 还是很陌生,所以我以前从未真正需要使用它。我正在从我的项目中的 API 调用中检索数据。我想通过向对象添加新属性来修改数据。但是,因为代码不是同步运行的,所以返回的是未修改的数组(我假设)而不是修改后的数组。
export function loadThings() {
return dispatch => {
return dispatch({
type: 'LOAD_THINGS',
payload: {
request: {
url: API_GET_THINGS_ENDPOINT,
method: 'GET'
}
}
}).then(response => {
let things = response.payload.data;
// Retrieve all items for the loaded "things"
if(things) {
things.forEach((thing, thingIndex) => {
things[thingIndex].items = []
if (thing.hasOwnProperty('channels') && thing.channels) {
thing.channels.forEach(channel => {
if (channel.hasOwnProperty('linkedItems') && channel.linkedItems) {
channel.linkedItems.forEach(itemName => {
dispatch(loadItems(itemName)).then(
item => things[thingIndex].items.push(item) // push the items inside the "things"
)
})
}
})
}
})
}
things.forEach(data => console.log(data.items.length, data.items)) // data.items.length returns 0, data.items returns a populated array
return things // return the modified array
}).catch(error => {
//todo: handle error
return false
})
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我执行了一个 API 调用,该调用返回名为response. 该数组填充了所有“事物”。如果things存在,我想加载名为“items”的额外信息。根据 things 数组中的信息,我将执行另一个 API 调用(这是通过调度loadItems函数完成的),它返回另一个promise. 根据该 API 调用结果中的数据,我将推入对象的items属性(它是一个数组)things。
正如你在评论中看到的,如果我遍历things数组并记录items我刚刚创建的属性,它基本上返回 0 作为长度,这意味着在修改数组things之前返回things数组。
我想知道两件事:
dispatch(loadItems(itemName))函数,因为它返回了一个承诺?请注意:此函数loadThings()还会返回一个 promise(如果您不熟悉 redux)。
您可能有兴趣了解我尝试自己修复代码的内容
由于我无法理解为什么代码异步运行的逻辑,我一直在尝试无望的东西。例如将代码包装在另一个中Promise.all并在该承诺中返回修改后的数组。我使用该then承诺的方法来修改things数组,结果完全相同。可能return things是因为在那个之外被执行promise。
我真的很想知道发生了什么
编辑
我已loadItems()根据要求将代码添加到问题中:
export function loadItems(itemName) {
return dispatch => {
const url = itemName ? API_GET_ITEMS_ENDPOINT + `/${itemName}` : API_GET_ITEMS_ENDPOINT;
return dispatch({
type: 'LOAD_ITEMS',
payload: {
request: {
url: url,
method: 'GET'
}
}
}).then(response => {
return response.payload.data
})
}
}
Run Code Online (Sandbox Code Playgroud)
我的方法是映射things,为包装在 a 中的所有项目创建承诺数组Promise.all,这给你一个 的数组Promise.all。
然后你返回things这个 Promise 数组,Promise.all然后在下一个 then 块中,你可以使用一个简单的 for 循环将数组分配给每个 Promise thing:
export function loadThings() {
return dispatch => {
return dispatch({
type: 'LOAD_THINGS',
payload: {
request: {
url: API_GET_THINGS_ENDPOINT,
method: 'GET'
}
}
}).then(response => {
let things = response.payload.data;
// Retrieve all items for the loaded "things"
const items = things.map((thing) => {
const thingItems = []
if (thing.hasOwnProperty('channels') && thing.channels) {
thing.channels.forEach(channel => {
if (channel.hasOwnProperty('linkedItems') && channel.linkedItems) {
channel.linkedItems.forEach(itemName => {
thingItems.push(dispatch(loadItems(itemName)));
});
}
});
}
return Promise.all(thingItems);
});
return Promise.all([things, Promise.all(items)])
})
.then(([things, thingItems]) => {
things.forEach((thing, index) => {
thing.items = thingItems[index];
})
return things;
})
.catch(error => {
//todo: handle error
return false
})
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:您需要将dispatch(loadItmes(itemName))调用直接推送到thingItems.
| 归档时间: |
|
| 查看次数: |
214 次 |
| 最近记录: |