我有一個獲取資料的函式。
const fetchData = async (filter) => {
if (loading) return
loading = true
const data = await api(filter)
setData(data)
loading = false
}
我還有一個過濾器組件,當我更改過濾器時,它會fetchData()使用新的過濾器變數呼叫我的函式。
這一切都有效,但是有一個問題
當我切換過濾器但我的提取功能處于加載狀態時會出現此問題。這會導致 if 檢查失敗,我現在看到過時的資料,因為從未發生重新獲取。
我最初的想法是創建一個const q = []變數,在里面if (loading)我會推送我的過濾器,最后我會以某種方式重新獲取q陣列中的最后一個元素,然后清除該陣列。
我真的不知道如何執行重新獲取邏輯。一個setInterval(() => checkQ(), 1000)?好像不對
什么是更好的方法?
uj5u.com熱心網友回復:
您應該使用AbortController- 那是 的一部分fetch,因為我的經驗告訴我,發起新fetch請求并不難,但是當您發出第二個請求時,如何處理第一個請求?
這是一個可以完成您要求的操作的片段 - 但也會處理不必要的請求:
const { useState, useEffect } = React
const useFetchData = () => {
const [users, setUsers] = useState([])
let controller = null
const fetchData = () => {
console.log('fetch initiated')
if (controller) controller.abort()
controller = new AbortController();
const { signal } = controller;
fetch('https://jsonplaceholder.typicode.com/users', { signal })
.then(response => {
console.log('request response')
return response.json()
})
.then(json => {
console.log('retrieved list:', json)
setUsers(() => json || [])
})
.catch(err => {
if(err.name === "AbortError") {
console.warn('Abort error', err)
}
})
}
return { fetchData }
}
const FetchData = () => {
const { fetchData } = useFetchData()
return (
<div>
<button onClick={fetchData}>FETCH DATA</button><br />
</div>
)
}
const FetchAbortFetchData = () => {
const { fetchData } = useFetchData()
return (
<div>
<button onClick={() => {
fetchData()
fetchData()
}}>FETCH-ABORT-FETCH DATA</button><br />
</div>
)
}
const App = () => {
return (
<div>
<FetchData /><br />
<FetchAbortFetchData />
</div>
)
}
ReactDOM.render(<App />, document.getElementById('root'))
<script src="https://unpkg.com/react@17/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js" crossorigin></script>
<div id="root"></div>
uj5u.com熱心網友回復:
最簡單的方法是使用您的過濾條件作為鎖。
好處
- 總是立即獲取資料
- 僅使用來自最新過濾條件的結果呼叫 setData
- 簡單的
缺點
- 可能有多個并發請求
- 在過濾器之間來回切換可能會導致競爭條件。
let latestFilter = null;
const fetchData = async (filter) => {
// Check to see if its there's the same request already in progress
// Note: may need to deep equal to check the filter
if (filter === latestFilter) return;
// Set the current request as most up to date
latestFilter = filter
// Fetch Data (async)
const data = await api(filter)
// If the filter is still the most up to date, use it. Otherwise discard.
// Note: may need to deep equal to check the filter
if (filter === latestFilter) {
setData(data)
latestFilter = null
}
}
為了解決缺點 2,您可以包含一個計數器。這將確保只有最近的請求才會運行 setData。
let latestFilter = null;
let latestRequestNumber = 0
const fetchData = async (filter) => {
if (filter === latestFilter) return;
latestFilter = filter
// Identify the current request
const requestNumber = latestRequestNumber 1;
// Store this number
latestRequestNumber = requestNumber
const data = await api(filter)
// Update data only if we are the most recent request.
if (callCount = latestCallCount) {
setData(data)
latestFilter = null
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/377471.html
標籤:javascript 反应 异步
下一篇:C#異步Foreach
