我正在使用React Native开发应用程序。我必须从URL提取类别的数据数组,然后对于每个类别,我必须从其各自的URL提取资产。
我的数据以以下格式存储:
来自mainURL
:
{
"id": 1,
"name": "Home",
"type": "",
"url": "",
"subCategories": [
{
"id": 92,
"name": "Documentary",
"type": "JTV_LEAF",
"url": "yyy",
}
]
}
从每个类别URL,
[
{
"id": "1",
"title": "Inception",
"type": "vod"
}
]
如何使用map
和reduce
和axios
获取每个类别的数据?
这是我到目前为止所写的。最后我得到undefined
。
export const fetchNavigationFeed = (navUrl, subId) => {
return dispatch => {
const url = navUrl
.replace("__JTV__SUBSCRIBER__ID__", subId);
dispatch({ type:FETCH_NAVIGATION_FEED });
return axios.get(url)
.then(response => {
let categories = [];
for (var i = 0; i < response.data.subCategories.length; i++) {
var cat = response.data.subCategories[i];
var category = new Category(cat);
categories.push(category);
}
console.log(categories);
let promises = [];
categories.map(category => {
let request = axios.get(category.url)
.then(assetsJson => {
let assets = [];
for (var i = 0; i < assetsJson.data.length; i++) {
var ass = assetsJson.data[i];
var asset = new Asset(ass);
assets.push(asset);
}
category.assets = assets;
});
promises.push(request);
});
axios.all(promises)
.then(axios.spread(...args) => {
console.log(args);
});
return categories;
})
.then(categories => {
// console.log(categories);
dispatch({ type:FETCH_NAVIGATION_FEED_SUCCESS, payload:categories });
});
}
}
答案 0 :(得分:4)
这是一个有效的示例,并进行了jest
测试:
code.js
import axios from 'axios';
export const FETCH_NAVIGATION_FEED = 'FETCH_NAVIGATION_FEED';
export const FETCH_NAVIGATION_FEED_SUCCESS = 'FETCH_NAVIGATION_FEED_SUCCESS';
class Category {
constructor(json) {
this.id = json.id;
this.name = json.name;
this.url = json.url;
}
}
class Asset {
constructor(json) {
this.id = json.id;
this.title = json.title;
}
}
export const fetchNavigationFeed = (navUrl, subId) => {
return async (dispatch) => {
dispatch({ type: FETCH_NAVIGATION_FEED });
const url = navUrl
.replace('__JTV__SUBSCRIBER__ID__', subId);
const response = await axios.get(url);
const categories = [];
const promises = [];
response.data.subCategories.forEach((subCategory) => {
const category = new Category(subCategory);
categories.push(category);
const promise = axios.get(category.url).then((subResponse) => {
category.assets = [];
subResponse.data.forEach((asset) => {
category.assets.push(new Asset(asset));
});
});
promises.push(promise);
});
// wait for all the promises simultaneously
await Promise.all(promises);
dispatch({ type: FETCH_NAVIGATION_FEED_SUCCESS, payload: categories });
}
}
code.test.js
import axios from 'axios';
import {
fetchNavigationFeed,
FETCH_NAVIGATION_FEED,
FETCH_NAVIGATION_FEED_SUCCESS
} from './code';
const getMock = jest.spyOn(axios, 'get');
getMock.mockImplementation((url) => {
switch (url) {
case 'mainUrl-mySubId':
return Promise.resolve({
data: {
"id": 1,
"name": "home",
"subCategories": [
{
"id": 2,
"name": "sub1",
"url": "sub1Url",
},
{
"id": 3,
"name": "sub2",
"url": "sub2Url",
}
]
}
});
case 'sub1Url':
return Promise.resolve({
data: [
{
"id": 4,
"title": "asset1"
},
{
"id": 5,
"title": "asset2"
}
]
});
case 'sub2Url':
return Promise.resolve({
data: [
{
"id": 6,
"title": "asset3"
},
{
"id": 7,
"title": "asset4"
}
]
});
}
});
test('getData', async () => {
const asyncDispatch = fetchNavigationFeed('mainUrl-__JTV__SUBSCRIBER__ID__', 'mySubId');
const dispatch = jest.fn();
await asyncDispatch(dispatch);
expect(dispatch).toHaveBeenCalledTimes(2);
const firstCallArgs = dispatch.mock.calls[0];
expect(firstCallArgs).toEqual([{
type: FETCH_NAVIGATION_FEED
}]);
const secondCallArgs = dispatch.mock.calls[1];
expect(secondCallArgs).toEqual([{
type: FETCH_NAVIGATION_FEED_SUCCESS,
payload: [
{
id: 2,
name: 'sub1',
url: 'sub1Url',
assets: [
{
"id": 4,
"title": "asset1"
},
{
"id": 5,
"title": "asset2"
}
]
},
{
id: 3,
name: 'sub2',
url: 'sub2Url',
assets: [
{
"id": 6,
"title": "asset3"
},
{
"id": 7,
"title": "asset4"
}
]
}
]
}]);
});
请注意:您可以使用axios.all()
,但根据this thread,它仍然可以使用Promise.all()
。
答案 1 :(得分:-1)
您可以执行以下操作:
fetch(url)
.then((response) => response.json())
.then(async (data) => {
const categories = data.subCategories
.map(category => new Category(category.id, category.name, category.type, category.url))
for(category of categories) {
let assets = await fetch(category.url).then(rsp => rsp.json())
assets = assets.map(asset => Asset(assets.id, assets.title, assets.type, ass.thumbnail));
category.assets = assets;
}
return categories
}).then(categoriesWithAssets => {/*done*/})