使用 Promis.all 处理多个 api 调用并使用 react-redux 处理数据
Handling multiple api calls with Promis.all and manipulating the data with react-redux
我正在构建一个带有 react/redux 的应用程序,用于管理 Collection 电子设备(=捐赠)。
在第一阶段,我需要进行 2 次 api 调用:
第一个和第二个是捐赠数据和捐赠者数据(在mongodb中保持不同collections),然后将它们合并。此信息显示在捐赠路线中。
动作看起来像这样:
const basicUrl = 'http://localhost:8000/api';
export const requestDonor_DonationData = () => getDonationData (
`${basicUrl}/donor`,
`${basicUrl}/donation`
);
getDonationData 函数如下所示:
import {
REQUEST_ENTITIES_PENDING,
REQUEST_ENTITIES_SUCCES,
REQUEST_ENTITIES_FAILED
} from './constants';
export const getDonationData = (urlDonor, urlDonation) => (dispatch) => {
dispatch ( {type: REQUEST_ENTITIES_PENDING} );
Promise.all([
fetch(urlDonor).then(res => res.json()),
fetch(urlDonation).then(res => res.json())
]).then ( ([ donorResult, donationResult]) => donorResult.data.map( (e, i) => Object.assign(e, donationResult.data[i]) ) )
.then( mergedData => dispatch({type: REQUEST_ENTITIES_SUCCES, payload: mergedData }) )
.catch(error => dispatch({type: REQUEST_ENTITIES_FAILED, payload: error}) )
}
效果不错。
在第二阶段,当一个捐赠被偷看后,它变成了一个设备(不是完美的词..),这意味着现在它正在等待检查。此信息显示在设备路线中。
设备数据包含 donationId 和状态(不同于捐赠状态)。
现在我想做类似的事情:
拨打 3 api 次电话(获取捐赠者、捐赠和设备数据)
合并捐赠者及其捐赠数据
过滤合并
已查看的捐赠数据 (status='DONE')
创建一个新的 json,它采用合并的数据并替换 ID 和
捐赠状态与设备的 ID 和状态。
我试过了
使用第一种方法(仅使用 Promise.all)来做到这一点,但发现
使用多个“.then”非常令人困惑...
这是我尝试过的:
行动-
export const requestEquipmentData = () => getEquipmentData (
[
`${basicUrl}/donor`,
`${basicUrl}/donation`,
`${basicUrl}/equipment`
]
);
export const getEquipmentData = (urls) => (dispatch) => {
dispatch ( {type: REQUEST_ENTITIES_PENDING} );
try {
const [ donorResult, donationResult, equipmentResult ] = Promise.all(urls.map(async function(url) {
const response = await fetch(url);
return response.json();
}));
const donationInfo = donorResult.data.map( (e, i) => Object.assign(e, donationResult.data[i]) );
const filteredDonation = donationInfo.filter(item =>item.status==='DONE');
const equipment = filteredDonation.map( (donation,i) => {
let obj = donation;
obj.id = equipmentResult.data[i].id;
obj.status = equipmentResult.data[i].status;
return obj;
})
dispatch({type: REQUEST_ENTITIES_SUCCES, payload: equipment });
} catch (error) {
dispatch({type: REQUEST_ENTITIES_FAILED, payload: error})
}
}
但是我做错了,那就是错误:
type: "REQUEST_ENTITIES_FAILED", payload: TypeError: undefined is not a function
如有任何帮助,我将不胜感激
Promise.all()
的结果是 Promise
,解析为 array
结果。它本身不是一个数组,所以你不能像这样解构它。
您可以使用与第一个示例相同的 .then()
方法:
export const getEquipmentData = (urls) => (dispatch) => {
dispatch({ type: REQUEST_ENTITIES_PENDING });
Promise.all(urls.map(async function (url) {
const response = await fetch(url);
return response.json();
})).then(([donorResult, donationResult, equipmentResult]) => {
const donationInfo = donorResult.data.map((e, i) => Object.assign(e, donationResult.data[i]));
const filteredDonation = donationInfo.filter(item => item.status === 'DONE');
const equipment = filteredDonation.map((donation, i) => {
let obj = donation;
obj.id = equipmentResult.data[i].id;
obj.status = equipmentResult.data[i].status;
return obj;
})
dispatch({ type: REQUEST_ENTITIES_SUCCES, payload: equipment });
}).catch(error) {
dispatch({ type: REQUEST_ENTITIES_FAILED, payload: error })
}
}
或者您可以使用 async
/await
语法。 有关解决 Promise 数组的一般性讨论。
export const getEquipmentData = (urls) => async (dispatch) => {
dispatch ( {type: REQUEST_ENTITIES_PENDING} );
try {
const [ donorResult, donationResult, equipmentResult ] = await Promise.all(urls.map(async function(url) {
const response = await fetch(url);
return response.json();
}));
const donationInfo = donorResult.data.map( (e, i) => Object.assign(e, donationResult.data[i]) );
const filteredDonation = donationInfo.filter(item =>item.status==='DONE');
const equipment = filteredDonation.map( (donation,i) => {
let obj = donation;
obj.id = equipmentResult.data[i].id;
obj.status = equipmentResult.data[i].status;
return obj;
})
dispatch({type: REQUEST_ENTITIES_SUCCES, payload: equipment });
} catch (error) {
dispatch({type: REQUEST_ENTITIES_FAILED, payload: error})
}
}
在我看来,您在这里的一般方法并不好。您应该阅读 Normalizing State Shape 上的指南。您的 API 似乎正在返回规范化数据,然后您通过组合来自多个端点的数据对其进行“非规范化”。
我正在构建一个带有 react/redux 的应用程序,用于管理 Collection 电子设备(=捐赠)。 在第一阶段,我需要进行 2 次 api 调用: 第一个和第二个是捐赠数据和捐赠者数据(在mongodb中保持不同collections),然后将它们合并。此信息显示在捐赠路线中。 动作看起来像这样:
const basicUrl = 'http://localhost:8000/api';
export const requestDonor_DonationData = () => getDonationData (
`${basicUrl}/donor`,
`${basicUrl}/donation`
);
getDonationData 函数如下所示:
import {
REQUEST_ENTITIES_PENDING,
REQUEST_ENTITIES_SUCCES,
REQUEST_ENTITIES_FAILED
} from './constants';
export const getDonationData = (urlDonor, urlDonation) => (dispatch) => {
dispatch ( {type: REQUEST_ENTITIES_PENDING} );
Promise.all([
fetch(urlDonor).then(res => res.json()),
fetch(urlDonation).then(res => res.json())
]).then ( ([ donorResult, donationResult]) => donorResult.data.map( (e, i) => Object.assign(e, donationResult.data[i]) ) )
.then( mergedData => dispatch({type: REQUEST_ENTITIES_SUCCES, payload: mergedData }) )
.catch(error => dispatch({type: REQUEST_ENTITIES_FAILED, payload: error}) )
}
效果不错。
在第二阶段,当一个捐赠被偷看后,它变成了一个设备(不是完美的词..),这意味着现在它正在等待检查。此信息显示在设备路线中。 设备数据包含 donationId 和状态(不同于捐赠状态)。 现在我想做类似的事情:
拨打 3 api 次电话(获取捐赠者、捐赠和设备数据)
合并捐赠者及其捐赠数据
过滤合并 已查看的捐赠数据 (status='DONE')
创建一个新的 json,它采用合并的数据并替换 ID 和 捐赠状态与设备的 ID 和状态。
我试过了 使用第一种方法(仅使用 Promise.all)来做到这一点,但发现 使用多个“.then”非常令人困惑...
这是我尝试过的: 行动-
export const requestEquipmentData = () => getEquipmentData (
[
`${basicUrl}/donor`,
`${basicUrl}/donation`,
`${basicUrl}/equipment`
]
);
export const getEquipmentData = (urls) => (dispatch) => {
dispatch ( {type: REQUEST_ENTITIES_PENDING} );
try {
const [ donorResult, donationResult, equipmentResult ] = Promise.all(urls.map(async function(url) {
const response = await fetch(url);
return response.json();
}));
const donationInfo = donorResult.data.map( (e, i) => Object.assign(e, donationResult.data[i]) );
const filteredDonation = donationInfo.filter(item =>item.status==='DONE');
const equipment = filteredDonation.map( (donation,i) => {
let obj = donation;
obj.id = equipmentResult.data[i].id;
obj.status = equipmentResult.data[i].status;
return obj;
})
dispatch({type: REQUEST_ENTITIES_SUCCES, payload: equipment });
} catch (error) {
dispatch({type: REQUEST_ENTITIES_FAILED, payload: error})
}
}
但是我做错了,那就是错误:
type: "REQUEST_ENTITIES_FAILED", payload: TypeError: undefined is not a function
如有任何帮助,我将不胜感激
Promise.all()
的结果是 Promise
,解析为 array
结果。它本身不是一个数组,所以你不能像这样解构它。
您可以使用与第一个示例相同的 .then()
方法:
export const getEquipmentData = (urls) => (dispatch) => {
dispatch({ type: REQUEST_ENTITIES_PENDING });
Promise.all(urls.map(async function (url) {
const response = await fetch(url);
return response.json();
})).then(([donorResult, donationResult, equipmentResult]) => {
const donationInfo = donorResult.data.map((e, i) => Object.assign(e, donationResult.data[i]));
const filteredDonation = donationInfo.filter(item => item.status === 'DONE');
const equipment = filteredDonation.map((donation, i) => {
let obj = donation;
obj.id = equipmentResult.data[i].id;
obj.status = equipmentResult.data[i].status;
return obj;
})
dispatch({ type: REQUEST_ENTITIES_SUCCES, payload: equipment });
}).catch(error) {
dispatch({ type: REQUEST_ENTITIES_FAILED, payload: error })
}
}
或者您可以使用 async
/await
语法。
export const getEquipmentData = (urls) => async (dispatch) => {
dispatch ( {type: REQUEST_ENTITIES_PENDING} );
try {
const [ donorResult, donationResult, equipmentResult ] = await Promise.all(urls.map(async function(url) {
const response = await fetch(url);
return response.json();
}));
const donationInfo = donorResult.data.map( (e, i) => Object.assign(e, donationResult.data[i]) );
const filteredDonation = donationInfo.filter(item =>item.status==='DONE');
const equipment = filteredDonation.map( (donation,i) => {
let obj = donation;
obj.id = equipmentResult.data[i].id;
obj.status = equipmentResult.data[i].status;
return obj;
})
dispatch({type: REQUEST_ENTITIES_SUCCES, payload: equipment });
} catch (error) {
dispatch({type: REQUEST_ENTITIES_FAILED, payload: error})
}
}
在我看来,您在这里的一般方法并不好。您应该阅读 Normalizing State Shape 上的指南。您的 API 似乎正在返回规范化数据,然后您通过组合来自多个端点的数据对其进行“非规范化”。