代码之家  ›  专栏  ›  技术社区  ›  khateeb

如何在JS中映射一个对象数组并获取每个对象的网络数据?

  •  3
  • khateeb  · 技术社区  · 6 年前

    我正在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 });
          });
      }
    }
    
    2 回复  |  直到 6 年前
        1
  •  4
  •   Brian Adams    6 年前

    这是一个有效的例子 jest


    代码.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 });
      }
    }
    

    代码.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()

        2
  •  -1
  •   Titus    6 年前

    你可以这样做:

    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*/})