【问题标题】:Code block runs before api call gets a response代码块在 api 调用得到响应之前运行
【发布时间】:2020-02-10 08:44:56
【问题描述】:

第二个 useEffect 块在第一个接收到任何数据之前运行。这会导致第二个块返回一个错误和一个空数组。

我尝试过使用 async/await,因为它过去曾为我解决过类似的问题。不过这里好像没什么效果。

    const [session, setSession] = useState("");
    const [champions, setChampions] = useState([]);

    useEffect(() => {
        axios.get(`http://api.paladins.com/paladinsapi.svc/createsessionJson/${devId}/${generateSignature('createsession')}/${moment.utc().format('YYYYMMDDHHmmss')}`).then((response) => {
            setSession(response.data.session_id);
            console.log(session);
        }).catch((error) => {
            console.log(error);
        })
    }, [])

    useEffect(() => {
        axios.get(`http://api.paladins.com/paladinsapi.svc/getchampionsJson/${devId}/${generateSignature('getchampions')}/${session}/${moment.utc().format('YYYYMMDDHHmmss')}/1`).then((response) => {
            setChampions(response.data);
            console.log(champions);
        }).catch((error) => {
            console.log(error);
        })
    }, []);

它应该向冠军返回一个对象数组,但由于它没有收到会话 id,因此 api 调用不是将冠军保持为空数组的正确地址。

【问题讨论】:

  • useEffect(可能)或 axious.get(肯定)是异步函数。谷歌了解它在 JavaScript 中的含义。通常你需要第一次调用它,然后在回调中进行第二次调用,比如 axious.get(oneCall).success(() => {axiouse.get(... etc.
  • 这给了我一个错误提示“.success 不是函数”。

标签: javascript ajax reactjs axios


【解决方案1】:

useEffect 是一个异步函数,因此您只需将调用都移到一个 useEffect 函数中,然后同步调用您的 api。我会将它移到一个单独的函数中,并使用 async/await 同步运行您的 api 调用。然后在你的 useEffect 函数中调用该函数,如下所示:

useEffect(() => {
  getData();
},[]);

const getData = async () => {
  try{
    const session = await axios.get(`your first call here`);
    const champions = await axios.get(`your second call here`);

    setSession(session.yourData);
    setChampions(champions.yourData);
  }catch(err){
    console.log(err);
  }
} 

如果您有来自第二个使用的第一个 api 调用的数据,那么您不需要将其设置为任何状态对象,您可以直接在第二个 api 调用中使用它。

【讨论】:

  • 使用这个我仍然遇到同样的问题。它仍然在第二个 axios 调用中返回一个空字符串,导致找不到调用的 url。
  • 如何将会话 ID 设置为第二个请求?而不是将 sessionid 设置为 state,您应该将 sessionid 直接设置为第一个 api 请求的第二个 api 请求。因此,与其将 response.data.session_id 设置为状态,不如将 session.data.session_id 直接设置到第二个 api 调用中。
  • 这样做我不再收到 404 not found 错误,但是,它似乎仍然没有更新 Champions 数组。使用:setChampions(myChamps.data);
  • 好像是在接收数据之前设置了setChampions数组
【解决方案2】:

    const [session, setSession] = useState("");
    const [champions, setChampions] = useState([]);

    useEffect(() => {
  try{
    const session = await axios.get(`http://api.paladins.com/paladinsapi.svc/createsessionJson/${devId}/${generateSignature('createsession')}/${moment.utc().format('YYYYMMDDHHmmss')}`);

    setSession(session.session_id);

    const champions = await axios.get(`http://api.paladins.com/paladinsapi.svc/getchampionsJson/${devId}/${generateSignature('getchampions')}/${session.session_id}/${moment.utc().format('YYYYMMDDHHmmss')}/1`);

    setChampions(champions );
     }
catch(err){
    console.log(err);
     }
}, [])



【讨论】:

  • 使用这个我仍然遇到同样的问题。它仍然在第二个 axios 调用中返回一个空字符串,导致找不到调用的 url。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-05
  • 1970-01-01
相关资源
最近更新 更多