javascript - 同步填充/修改数组并在 Promise 中返回修改后的数组
问题描述
我对 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
})
}
}
如您所见,我执行了一个 API 调用,它返回名为response
. 该数组填充了所有“事物”。如果things
存在,我想加载名为“项目”的额外信息。根据 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
})
}
}
解决方案
我的方法是 map over things
,为包裹在 a 中的所有项目创建 promise 数组,从而为您提供'sPromise.all
数组。Promise.all
然后你things
在另一个Promise.all
和下一个 then 块中返回这个 promise 数组,你可以thing
使用一个简单的 for 循环将数组分配给每个数组:
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
})
}
}
编辑:您需要将dispatch(loadItmes(itemName))
呼叫直接推送到thingItems
.
推荐阅读
- javascript - 使用 Ramda 将一组 id 映射到具有这些 id 的对象
- python - pd.read_csv:utf-8'编解码器无法解码位置 61 中的字节 0x98:无效的起始字节
- javascript - 如何在异步测试中计时 sinon 间谍
- android - 如何禁用 Android Studio 3.5 按字母顺序排序 xml 标签
- r - 循环网络爬虫,都是NA,但是一步一步正常
- javascript - 保存动态添加的包含图表的 div
- python - 如何从循环中的最后一项中删除昏迷?
- django - Django:在运行时加载模板
- jquery - Daterange picker posting data with ajax
- django - django 在 / 'file' 处引发 MultiValueDictKeyError