我正在处理我的一个小项目,就在部署之前,我使用的 API 进行了策略更改以将 API 调用限制为每秒一次。这导致我出现错误(错误 429:请求过多)。 我的解决方法(因为 axios 没有 retry after header prop 是使用 fetch API 创建某种递归函数,如果调用失败,它会再次调用)。所以,最初我最终得到了下面的代码块:
//recursive function to make an api call
const fetchCalls = useCallback((url, setState, retries = 4) => {
fetch(url)
.then((res) => {
// check if successful. If so, return the response transformed to json
if (res.ok) {
return res.json();
}
// else, return a call to fetchRetry if number of retries >0
if (retries > 0) {
return fetchCalls(url, setState, retries - 1);
} else {
throw new Error(res);
}
})
.then((data) => {
if (data !== undefined) {
setState(data);
Axios.all([
Axios.get(
`${api.sparklineBase}${setLowerCase(
data[0].name
)}/market_chart/range?vs_currency=${
userData.currency.code
}&from=${dayUNIX}&to=${currentUNIX}`
),
Axios.get(
`${api.sparklineBase}${setLowerCase(
data[0].name
)}/market_chart/range?vs_currency=${
userData.currency.code
}&from=${yearUNIX}&to=${currentUNIX}`
),
])
.then((ress) => {
setSparkline((prevState) => {
return [...prevState, ress[0].data];
});
setSparkline((prevState) => {
return [...prevState, ress[1].data];
});
})
.catch((errr) => {
console.log(errr);
});
}
// Do something with the response
})
.catch((error) => {
console.log(error);
});
}, [userData, setSparkline]);
useEffect(() => {
Axios.get(`${api.zoneBase}apiKey=${api.zoneKey}&include=useragent`)
.then((response) => {
setUserData(response.data);
//calling fetchCalls function below
fetchCalls( `${api.base}key=${api.key}&ids=${match.params.id}&convert=${response.data.currency.code}&interval=1d,7d,30d,365d`,
setCryptos
);
})
.catch((err) => {
console.log(err);
});
return () => {
setCryptos([]);
setSparkline([]);
};
}, [setCryptos, setSparkline, setUserData, match, fetchCalls, cryptos]);
显然它导致了如此多的重新渲染猜测导致 useEffect 和 useCallback 中的一些依赖项是实际的异步状态值。
决定将 fetchCall(没有 useCallback)扔到 useEffect 中,我最终得到了这个:
//forgot to comment out this bit.
const fetchCalls = useCallback((url, setState, retries = 4) => {
fetch(url)
.then((res) => {
// check if successful. If so, return the response transformed to json
if (res.ok) {
return res.json();
}
// else, return a call to fetchRetry
if (retries > 0) {
return fetchCalls(url, setState, retries - 1);
} else {
throw new Error(res);
}
})
.then((data) => {
if (data !== undefined) {
setState(data);
}
// Do something with the response
})
.catch((error) => {
console.log(error);
});
}, []);
useEffect(() => {
Axios.get(`${api.zoneBase}apiKey=${api.zoneKey}&include=useragent`)
.then((response) => {
setUserData(response.data);
const fetchCalls = (url, setState, retries = 4) => {
fetch(url)
.then((res) => {
// check if successful. If so, return the response transformed to json
if (res.ok) {
return res.json();
}
// else, return a call to fetchRetry
if (retries > 0) {
return fetchCalls(url, setState, retries - 1);
} else {
throw new Error(res);
}
})
.then((data) => {
if (data !== undefined) {
setState(data);
Axios.all([
Axios.get(
`${api.sparklineBase}${setLowerCase(
data[0].name
)}/market_chart/range?vs_currency=${
response.data.currency.code
}&from=${dayUNIX}&to=${currentUNIX}`
),
Axios.get(
`${api.sparklineBase}${setLowerCase(
data[0].name
)}/market_chart/range?vs_currency=${
response.data.currency.code
}&from=${weekUNIX}&to=${currentUNIX}`
),
])
.then((ress) => {
setSparkline((prevState) => {
return [...prevState, ress[0].data];
});
setSparkline((prevState) => {
return [...prevState, ress[1].data];
});
})
.catch((errr) => {
console.log(errr);
});
}
// Do something with the response
})
.catch((error) => {
console.log(error);
});
};
fetchCalls(
`${api.base}key=${api.key}&ids=${match.params.id}&convert=${response.data.currency.code}&interval=1d,7d,30d,365d`,
setCryptos
);
})
.catch((err) => {
console.log(err);
});
return () => {
setCryptos([]);
setSparkline([]);
};
}, [setCryptos, setSparkline, setUserData, match, fetchCalls]);
上面的代码按预期工作。然而,我不知道我忘记注释掉原始的 fetchCalls 函数(在 useEffect 之外),因为我只注释掉了依赖于 API 调用 fetchCalls 函数的第二组 API 调用。现在尝试将其注释掉会导致错误,指出未定义 fetchCalls 并且 fetchCalls 是不必要的依赖项。
但是请注意,在第二个代码块中,useEffect 中的 fetchCalls 承载了第二组 API 调用,这些 API 调用依赖于 useEffect 中的 fetchCalls 函数应该进行的 API 调用。
现在我只想知道为什么它会这样工作,因为我觉得这一切都很奇怪。另外,我可以使用更可接受的解决方法吗?