【问题标题】:SWAPI does not return all people after selecting a film选择电影后,SWAPI 不会返回所有人
【发布时间】:2021-09-06 21:46:47
【问题描述】:

所以我正在做一个小应用程序,使用 swapi.dev/ 检索星球大战中出现的所有角色。

它应该工作的方式是,一旦我选择了一部电影,其中的所有角色都应该出现,但是,在选择不同的电影时,我会得到不同的结果,例如,如果我选择《星球大战前传 4》 ,我最多有 10 个字符,我显然应该有更多(如果我是正确的,18 个),如果我选择第 1 集,我只会得到 3 个人。这是我用来吸引人的代码:

async function fetchPeople() {
    let res = await fetch('https://swapi.dev/api/people/');
    let data = await res.json();
    return data.results;
}


export const showPeople = async (movies) => {
    const people = await fetchPeople();
    const matchingPeople = [];
    console.log('char count: ', movies.characters.length);
    console.log('peopel count: ', people.length);
    movies.characters.forEach((movieCharacter) => {
        people.forEach((person) => {
            const isMatching = person.url === movieCharacter;
            if (isMatching) {
                matchingPeople.push(person);
            }
        });
    });
    return matchingPeople;
}

现在是棘手的部分:当我 console.log “char count”时,我得到了正确数量的字符(在第 4 集 18 个字符的情况下,在 API 中,但是在 console.log “peopel数”,我最多只能得到 10 个。它变得更奇怪了。

这里是 React 组件用于显示电影的代码:

import React from 'react'
import { Card, Grid, Button } from 'semantic-ui-react'
import {showPeople} from '../controllers/ShowPeople'
// import fakedata from '../fakedata.json'


const Movies = ({data, setPeople}) => {
    console.log(setPeople)
    return (
        <>
        <h1>Movies</h1>
        <Grid columns={3}>
            {data && data.map((movies, i) => {
                return (
                    <Grid.Column key={i}>
                        <Card>
                            <Card.Content>
                                <Card.Header>{movies.title}</Card.Header>
                                <Card.Description>
                                    <strong>Episode</strong>
                                    <p>{movies.episode_id}</p>
                                    <strong>Release</strong>
                                    <p>{movies.release_date}</p>
                                </Card.Description>
                            <Button onClick={ async () => {
                                const people = await showPeople(movies)
                                console.log('test people ',people)
                                setPeople(people)
                            } }>
                                Show People
                            </Button>
                            </Card.Content>
                        </Card>
                    </Grid.Column>
                )
            })}
        </Grid>
    </>
    )
}

export default Movies;

现在,在 console.log("test people") 中,我得到不同的数组结果,具体取决于我选择的电影,有时 6 人,有时 3 人,有时 10 人,但不超过 10 人。

Chrome console screenshot:

可能是什么问题?起初我以为 API 限制了我的请求,但我怀疑我每天在这个 API 上实现 10k 请求。也许问题出在 showPeople 函数上?

Full code on github for more clarity

【问题讨论】:

  • https://swapi.dev/api/people/ 的第一页上只有 10 个元素 - 如果您查看 that page,您会看到它有一个名为“next”的属性,它有一个不同的 url,可以为您提供下一个 10等。
  • 使用 apis 的一个常见做法是将结果限制为 x 个数字。星球大战 api 每个“页面”使用 10 个结果。这样做有多种原因,但它导致您需要其他 api 请求。如果您检查 json 请求中的下一个属性,您会看到它将包含一个“?page=2”。如果您添加它,您将获得 10 个以上(或者在您的情况下,第 4 集将获得 8 个以上)。
  • @James 哦,废话,你是对的!那么我如何编码程序,以利用“下一个”属性? API链接是否应该以某种方式编写?
  • 检查该 api 的文档以获得可能性 一些 api 允许您将“页面大小”更改为一定数量。如果星球大战 api 提供此选项,您可以通过查询参数执行此操作。如果 api 没有提供此解决方案,您可以再次查看文档。如果没有可用的下一页,则 next 属性将为空。您可以继续获取结果并将结果附加到 js 数组,直到没有剩余的 api 请求。或者你可以做一些数学运算并发送多个 api 请求。小心不要进行无限循环,您可能会因为发送过多垃圾邮件而被列入黑名单。

标签: javascript reactjs


【解决方案1】:

您可能需要再次查看 api 的文档。

以这个网址为例:api/people/?page=7

{
    "count": 82, 
    "next": "https://swapi.dev/api/people/?page=8", 
    "previous": "https://swapi.dev/api/people/?page=6", 
    "results": [...] //10 results
}

如您所见,这再次显示了 10 个结果。因此我们可以得出结论,每次 api 调用在 results 属性中,api 将始终返回最多 10 个项目。

大多数 API 提供 2 种不同的解决方案。

  1. 他们可能有一个属性可以让您更改pageSize。例如,这可能用于在一次 api 调用中返回 50 个对象。
  2. 最常见的是它们将具有page 属性。您将需要第二次 api 调用来获取接下来的 x (10) 项。

我能想到两种不同的解决方案。

您可以使用next 属性。如果数据集非常大并且您想使用分页,这是一个好方法。

您还可以做一些简单的数学运算并使用count 属性。例如,想要的 api 调用有 82 个项目。您可以将其除以 10。您将得到 8.2 并将其四舍五入。您现在知道它将有 9 个页面,因此您可以发送 9 个 api 调用。但请记住,这对 API 来说不是那么友好,并且一些公共 API 可能有一些低速率限制。如果您在短时间内发送大量请求,您可能会被列入黑名单。

如果您收到了结果,请将结果附加到本地数组中,然后您可以对它做任何您想做的事情(即显示信息)。

但重要的一点是性能。您希望您的客户加载 82 张不同的图片吗?当您通过新的 api 调用向下滚动时,您可能还想处理页面或数据加载。

【讨论】:

  • 感谢您提供信息丰富的回答!我还查看了 stackoverflow 是否存在类似问题,并且我找到了一个使用递归的解决方案,这对我来说非常有效。进一步研究后,如果我没记错的话,程序会执行几个 API 调用并将所有数据加载到内存中。这是解决方案的链接:stackoverflow.com/questions/49129245/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多