我在一個站點中有一個頁面,旨在顯示三個 API 的 API 資料。當我點擊這個頁面時,前兩個 API 加載,但第三個沒有。
每個 API 使用一組引數。例如,第一個 API 在 url 中有平臺、地區和用戶名。引數存盤在我為此專案創建的 firestore 資料庫中。
當我開始這個腳本時,我最初對引數進行了硬編碼,所有三個 API 都沒有出現問題。然而,當我開始從 firestore 資料庫中提取引數時,我創建了一個競爭條件。
我已將我的問題縮小到這一點:這個腳本應該按順序運行一次,但它現在在添加資料庫拉取后無限運行。這意味著每個 API 查詢都運行不止一次。由于從資料庫獲取引數存在延遲,因此腳本嘗試運行不帶引數的 API 查詢(因此不正確)。這將回傳一個錯誤并阻止第三個 API 加載。
我在下面包含了我的腳本,以及我的網站和控制臺的螢屏截圖。
// import React from "react";
import React, { useState, useEffect, useMemo, useRef } from "react";
// import "./Statsview.css";
import {database} from "./firebase";
import PersonIcon from '@material-ui/icons/Person';
import ForumIcon from "@material-ui/icons/Forum";
import IconButton from "@material-ui/core/IconButton";
import ArrowBackIosIcon from "@material-ui/icons/ArrowBackIos";
import {Link, useHistory, useParams} from "react-router-dom";
import { People } from "@material-ui/icons";
console.log('starting script');
var O_mostPlayed;
var O_winRatio;
var O_compED;
var O_avgE;
var A_compRank;
var A_arenaRank;
var A_level;
var A_kills;
var C_wins;
var C_losses;
var C_winRate;
function Statsview( {backButton} ) {
// getting api info from our db
const urlParams = new URLSearchParams(window.location.search);
const name = urlParams.get('name');
const chessName = urlParams.get('chess');
const [game1, setgame1] = useState("");
const [game2, setgame2] = useState("");
const [game3, setgame3] = useState("");
const [O_name, setO_name] = useState("");
const [O_platform, setO_platform] = useState("");
const [O_region, setO_region] = useState("");
const [A_name, setA_name] = useState("");
const [A_platform, setA_platform] = useState("");
const [C_name, setC_name] = useState("");
const [didO, setset_didO] = useState(false);
const [didA, setset_didA] = useState(false);
const [didC, setset_didC] = useState(false);
useEffect(() => {
database.collection('USERS').where('name','==',name).get().then(snapshot => {
snapshot.forEach(doc => {
const data = doc.data()
setgame1(data.game1);
setgame2(data.game2);
setgame3(data.game3);
setO_name(data.overwatch);
setO_platform(data.overwatchPlatform);
setO_region(data.overwatchRegion);
setA_name(data.apexLegends);
setA_platform(data.apexLegendsPlatform);
// setC_name(data.chess);
})
}).catch(error => console.log(error))
},[]);
var O_url = 'https://owapi.io/stats/' O_platform '/' O_region '/' O_name;
var A_url = 'https://api.mozambiquehe.re/bridge?version=5&platform=' A_platform '&player=' A_name '&auth=...';
// var C_url = 'https://api.chess.com/pub/player/' chessName '/stats';
var C_url = 'https://api.chess.com/pub/player/cnewby5283/stats';
console.log(C_url);
// console.log(O_url)
var request_O = new XMLHttpRequest();
var request_A = new XMLHttpRequest();
var request_C = new XMLHttpRequest();
// API queries
request_O.open('GET', O_url, true);
request_A.open('GET', A_url, true);
request_C.open('GET', C_url, true);
// potential API queries
// request.open('GET', 'https://api.clashroyale.com/v1/players/#9CCUURQVJ', true);
// request.setRequestHeader("authorization","Bearer [api key for specific IP]");
console.log('got queries');
if (O_name.localeCompare("") != 0 && O_platform.localeCompare("") != 0 && O_region.localeCompare("") != 0) {
console.log("O_url: ", O_url)
request_O.onload = function () {
var data = JSON.parse(this.response);
if (request_O.status >= 200 && request_O.status < 400) {
O_mostPlayed = "Most Played: " data.stats.top_heroes.competitive.played[0].hero ", " data.stats.top_heroes.competitive.played[1].hero ", " data.stats.top_heroes.competitive.played[2].hero;
O_winRatio = "Win Ratio: " (parseInt(data.stats.game.competitive[3].value) / parseInt(data.stats.game.competitive[1].value)).toFixed(3);
O_compED = "Competitive Elims/Deaths: " (parseInt(data.stats.combat.competitive[4].value) / parseInt(data.stats.combat.competitive[3].value)).toFixed(3);
O_avgE = "Avg. Eims / 10 Minutes: " data.stats.average.competitive[3].value;
document.getElementById("O_1").innerHTML = O_mostPlayed;
document.getElementById("O_2").innerHTML = O_winRatio;
document.getElementById("O_3").innerHTML = O_compED;
document.getElementById("O_4").innerHTML = O_avgE;
} else {
return (
<marquee>
API Request Failed
</marquee>
)
}
// didO = true;
}
request_O.send();
}
if (A_name.localeCompare("") != 0 && A_platform.localeCompare("") != 0) {
console.log("A_url: ", A_url)
request_A.onload = function () {
var data = JSON.parse(this.response);
if (request_O.status >= 200 && request_O.status < 400) {
A_compRank = "Competitive Rank : " data.global.rank.rankName " -- " data.global.rank.rankScore;
A_arenaRank = "Arena Rank : " data.global.arena.rankName " -- " data.global.arena.rankScore;
A_level = "Level : " data.global.level;
A_kills = "Kills : " data.total.kills.value;
document.getElementById("A_1").innerHTML = A_compRank;
document.getElementById("A_2").innerHTML = A_arenaRank;
document.getElementById("A_3").innerHTML = A_level;
document.getElementById("A_4").innerHTML = A_kills;
} else {
return (
<marquee>
API Request Failed
</marquee>
)
}
// didA = true;
}
request_A.send();
}
if (chessName.localeCompare("") != 0) {
console.log("C_url: ", C_url)
request_C.onload = function () {
// console.log("test chess query below 1");
var data = JSON.parse(this.response);
if (request_O.status >= 200 && request_O.status < 400) {
console.log("entered c if statement")
C_wins = "Wins : " data.chess_rapid.record.win;
C_losses = "Losses : " data.chess_rapid.record.loss;
C_winRate = "Win rate : " (parseInt(data.chess_rapid.record.win) / parseInt(data.chess_rapid.record.loss)).toFixed(3);
document.getElementById("C_1").innerHTML = C_wins;
document.getElementById("C_2").innerHTML = C_losses;
document.getElementById("C_3").innerHTML = C_winRate;
} else {
console.log("didnt enter c if statement")
return (
<marquee>
API Request Failed
</marquee>
)
}
// didC = true;
}
request_C.send();
}
return(
<div class="apiDisplays">
<div id="nameDisplay">
Meet {name}!<br/><br/>
</div>
<div id="gamesPlayedDisplay">
{/* show games */}
{name} plays these games: <br/>
{game1} <br/> {game2} <br/> {game3}
<br/><br/>
</div>
<div id="apiDisplay">
{/* shows api data */}
Avaliable stats for {name} <br/><br/>
</div>
<div>
<h1>Overwatch Stats</h1>
<p id="O_1">None</p>
<p id="O_2">None</p>
<p id="O_3">None</p>
<p id="O_4">None</p>
</div>
<div>
<h1>Apex Stats</h1>
<p id="A_1">None</p>
<p id="A_2">None</p>
<p id="A_3">None</p>
<p id="A_4">None</p>
</div>
<div>
<h1>Chess.com Stats</h1>
<p id="C_1">None</p>
<p id="C_2">None</p>
<p id="C_3">None</p>
</div>
</div>
)
}
export default Statsview

編輯:我在每個 API 呼叫之前都包含 if 陳述句,現在我沒有收到任何錯誤。
然而,第三個 API 仍然沒有顯示。這很有趣,因為我在 XMLHTTPRequest 中發送的 url 是正確的,如螢屏截圖所示。(我在第三個 if 陳述句中輸出了 url)。
如果我為 API 查詢發送正確的 url,為什么我的程式回傳此查詢的狀態不足?

uj5u.com熱心網友回復:
實際上,每次呈現組件時都會執行您的 API 呼叫,因為它們位于函式體中。React 組件只是普通的舊函式,因此每次 React 渲染您的組件時(閱讀:每次 React 呼叫您的函式時),無論引數狀態如何,您的組件都會運行所有 API 呼叫。那很糟!至少,您應該將 API 呼叫包裝在 useEffect 中,并在從 API 獲取之前測驗您是否已經擁有所需的引數:
// this is pseudocode, hopefully you get the idea
React.useEffect(() => {
if (dbParameters) {
// do your fetching
}
}, [dbParameters]);
你至少有點熟悉這個概念,因為你已經為 db 引數做過了!
我強烈建議通讀這篇文章幾次,它是處理 useEffect 和獲取資料的寶貴資源。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/373514.html
上一篇:APIFetch不提取資料
