日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

React 19 出手解決了異步請求的競態問題,是好事還是壞事?

來源: 責編: 時間:2024-06-07 17:20:19 293觀看
導讀是的,又是競態問題。在客戶端開發中,這是一個老生常態的問題。一個有經驗的前端工程師必定是對這個問題的情況與解決方案如數家珍。因此競態問題也經常在面試的過程中被討論。競態問題指的是,當我們在交互過程中,由于各種

Cuu28資訊網——每日最新資訊28at.com

是的,又是競態問題。Cuu28資訊網——每日最新資訊28at.com

在客戶端開發中,這是一個老生常態的問題。一個有經驗的前端工程師必定是對這個問題的情況與解決方案如數家珍。因此競態問題也經常在面試的過程中被討論。Cuu28資訊網——每日最新資訊28at.com

競態問題指的是,當我們在交互過程中,由于各種原因導致同一個接口短時間之內連續發送請求,后發送的請求有可能先得到請求結果,從而導致數據渲染出現預期之外的錯誤。Cuu28資訊網——每日最新資訊28at.com

有的地方也稱為競態條件Cuu28資訊網——每日最新資訊28at.com

因為防止重復執行可以有效的解決競態問題,因此許多時候面試官也會直接在面試中問我們如何實現防重。常用的方式就是取消上一次請求,或者設置狀態讓按鈕不能連續點擊,想必各位大佬對這些方案都已經非常熟悉,我這里就不展開細說。當然,這個問題雖然被經常討論,但是要解決好確實需要一點技術功底。Cuu28資訊網——每日最新資訊28at.com

React 19 結合 Suspense 也在競態問題上,提出了一個自己的解決方案。我們結合新的案例來探討一下這個問題,看完之后大家感受一下這種方式是好是壞。Cuu28資訊網——每日最新資訊28at.com

一、案例

我們先來看一下本次案例要實現的交互效果。如下圖所示。每次點擊會新增一條數據到下方的列表中。Cuu28資訊網——每日最新資訊28at.com

Cuu28資訊網——每日最新資訊28at.com

我們來實現一下這個效果,首先定義一個用于請求接口的 promise。Cuu28資訊網——每日最新資訊28at.com

const getApi = async () => {  const res = await fetch('https://api.chucknorris.io/jokes/random')  return res.json()}

然后和前面的案例一樣,我們將每次點擊的 api 作為狀態存儲起來,通過 api 的改變來觸發更新的執行。Cuu28資訊網——每日最新資訊28at.com

const [api, setApi] = useState(null)

與此同時,我們還需要一個數組作為狀態來管理列表。Cuu28資訊網——每日最新資訊28at.com

const [list, setList] = useState([])

有了這個數組之后,我們需要遍歷這個數組渲染成 UI。Cuu28資訊網——每日最新資訊28at.com

<div className="list">  {list.map((item, index) => {    return <div className='item' key={item}>{item}</div>  })}</div>

最后需要 loading 顯示的部分,我們使用 Suspense 來完成。Cuu28資訊網——每日最新資訊28at.com

<Suspense fallback={<div>loading...</div>}>  <Item api={api} setList={setList} /></Suspense>

需要注意的是,我們這里把 setList 傳遞進入了子組件。這個細節需要仔細思考我的動因。Cuu28資訊網——每日最新資訊28at.com

我們要考慮的問題是,當我們在 Suspense 之外,需要知道請求成功的狀態和數據時,只有在 Suspense 的子組件內部才可以獲取到。Suspense 子組件和外面的 Loading 是一個互斥的顯示關系。Cuu28資訊網——每日最新資訊28at.com

因此,我們要在子組件內部去獲取請求成功的數據結果。Cuu28資訊網——每日最新資訊28at.com

const Item = ({api, setList}) => {  const [show, setShow] = useState(true)  const joke = api ? use(api) : {value: 'nothing'}  useEffect(() => {    if (!api) return    setList((list) => {      if (!list.includes(joke.value)) {        return list.concat(joke.value)      }      return list    })    setShow(false)  }, [])  const __cls = show ? '_03_a_value show' : '_03_a_value'  return (    <div className={__cls}>{joke.value}</div>  )}

狀態 show 是為了讓最后一條數據在列表中顯示,而不在這里顯示。Cuu28資訊網——每日最新資訊28at.com

這里我們使用了 useEffect 來表示子組件渲染完成時需要執行的邏輯。注意 React 19 雖然通過很多方式大幅度弱化了 useEffect 的存在感,但是偶爾在合適的時候使用也是必要的。Cuu28資訊網——每日最新資訊28at.com

我在合并 list 的過程中,添加了一個判斷。Cuu28資訊網——每日最新資訊28at.com

setList((list) => {  if (!list.includes(joke.value)) {    return list.concat(joke.value)  }  return list})

這個細節在真實項目開發中尤其重要。因為 React 19 嚴格模式之下,組件會讓 useEffect 執行兩次,以模擬生產環境的重復請求問題,因此,我這里做了一個判斷方式同樣的數據連續推送到數組里,從而導致線上 bug 的發生。Cuu28資訊網——每日最新資訊28at.com

一個程序員是否經驗豐富,是否成熟,都是體現在這些生產環境的細節中。Cuu28資訊網——每日最新資訊28at.com

完整代碼如下:Cuu28資訊網——每日最新資訊28at.com

const getApi = async () => {  const res = await fetch('https://api.chucknorris.io/jokes/random')  return res.json()}export default function Index() {  const [api, setApi] = useState(null)  const [list, setList] = useState([])  function __clickToGetMessage() {    setApi(getApi())  }  return (    <div>      <div id='tips'>點擊按鈕新增一條數據,該數據從接口中獲取</div>      <button onClick={__clickToGetMessage}>新增數據</button>      <div className="content">        <div className="list">          {list.map((item, index) => {            return <div className='item' key={item}>{item}</div>          })}        </div>                <Suspense fallback={<div>loading...</div>}>          <Item api={api} setList={setList} />        </Suspense>      </div>    </div>  )}const Item = ({api, setList}) => {  const [show, setShow] = useState(true)  const joke = api ? use(api) : {value: 'nothing'}  useEffect(() => {    if (!api) return    setList((list) => {      if (!list.includes(joke.value)) {        return list.concat(joke.value)      }      return list    })    setShow(false)  }, [])  const __cls = show ? '_03_a_value show' : '_03_a_value'  return (    <div className={__cls}>{joke.value}</div>  )}

這樣之后,我們的目標基本就完成了。接下來,我們需要觀察,當我惡意重復點擊按鈕,會發生什么事情。Cuu28資訊網——每日最新資訊28at.com

二、連續點擊

惡意連續點擊之前,我根據我以往的經驗預測一下可能會發生什么事情。Cuu28資訊網——每日最新資訊28at.com

首先,多次點擊會導致多次請求,因此數組中會新增大量的數據。Cuu28資訊網——每日最新資訊28at.com

其次,由于請求太密集,那么點擊的先后順序,與請求成功的先后順序不一致,因此列表中的順序也會與點擊順序不同。「競態問題」Cuu28資訊網——每日最新資訊28at.com

那么我們來試著操作一下,看看該案例會有什么反應。演示結果如下,新增一條數據時,我連續點擊了 10 次。Cuu28資訊網——每日最新資訊28at.com

圖片Cuu28資訊網——每日最新資訊28at.com

結果我們發現,點擊期間,并沒有新的數據渲染到頁面上,一直是 loading 的狀態。Cuu28資訊網——每日最新資訊28at.com

再來看一下此時的請求情況。Cuu28資訊網——每日最新資訊28at.com

Cuu28資訊網——每日最新資訊28at.com

請求的順序被嚴格控制了:上一個請求請求成功之后,下一個請求才開始發生。此時是一個串行的請求過程。Cuu28資訊網——每日最新資訊28at.com

react 19 使用這種思路解決了競態問題。與此同時,反饋到數據上,雖然前面多次的請求已經成功,但是對于組件狀態來說,這個中間過程中一直有請求在發生,此時 React 認為中間的請求產生的數據為無效數據。只會把最后一個請求成功的數據作為最終的返回結果。Cuu28資訊網——每日最新資訊28at.com

三、是好是壞

很顯然,僅從 UI 結果上來說,這樣的處理方式確實是非常合理的,我們不需要過多的干涉數據的處理,非常的輕松。但問題是,每次請求都成功發生。Cuu28資訊網——每日最新資訊28at.com

當我點擊 10 次,就會有 10 次請求,由于使用串行的策略來解決競態問題,導致最后一次的請求結果需要等待很長實踐才會返回。這無疑極大的降低了開發體驗。Cuu28資訊網——每日最新資訊28at.com

和取消上一次的請求相比,無論是從體驗上,還是從效率上來說,無疑都是更差的一種方案。Cuu28資訊網——每日最新資訊28at.com

因此,我們可以簡單基于目前的代碼,使用禁用按鈕的方式,來防止重復請求。Cuu28資訊網——每日最新資訊28at.com

在父組件中定義一個狀態用于控制按鈕的禁用狀態。Cuu28資訊網——每日最新資訊28at.com

const [disabled, setDisabled] = useState(false)

并將其傳遞給按鈕 button 組件的 disabled 屬性。Cuu28資訊網——每日最新資訊28at.com

<button   disabled={disabled}   onClick={__clickToGetMessage}>新增數據</button>

點擊時,我們將其設置為 true,此時一個新的請求會發生。Cuu28資訊網——每日最新資訊28at.com

function __clickToGetMessage() {  setDisabled(true);  setApi(getApi())}

請求成功之后,我們在子組件的 useEffect 中,將其設置為 false。子組件代碼調整如下:Cuu28資訊網——每日最新資訊28at.com

const Item = ({api, setList, setDisabled}) => {  const [show, setShow] = useState(true)  const joke = api ? use(api) : {value: 'nothing'}  useEffect(() => {    if (!api) return+   setDisabled(false)    setList((list) => {      if (!list.includes(joke.value)) {        return list.concat(joke.value)      }      return list    })    setShow(false)  }, [])  const __cls = show ? '_03_a_value show' : '_03_a_value'  return (    <div className={__cls}>{joke.value}</div>  )}

演示效果如下:Cuu28資訊網——每日最新資訊28at.com

Cuu28資訊網——每日最新資訊28at.com

這種方式也可以比較合理的解決競態問題。Cuu28資訊網——每日最新資訊28at.com

后續我們通過別的案例,再來演示通過取消上一次的接口請求方式是如何實現的。Cuu28資訊網——每日最新資訊28at.com

本文鏈接:http://m.www897cc.com/showinfo-26-92747-0.htmlReact 19 出手解決了異步請求的競態問題,是好事還是壞事?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 大廠真實案例,CPU 升高問題如何排查?五分鐘掌握

下一篇: 從 Dapper 到 OpenTelemetry:分布式追蹤的演進之旅

標簽:
  • 熱門焦點
Top 日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不
国产毛片久久| 99re6这里只有精品| 欧美日韩精品一本二本三本| 欧美大片在线看| 欧美精品一区二区视频| 欧美日韩一区二区免费在线观看| 欧美三级中文字幕在线观看| 国产精品一区二区三区久久久| 国产一区二区在线免费观看| 在线观看一区视频| 国产精品99久久久久久久久 | 精品动漫3d一区二区三区免费版| 极品av少妇一区二区| 亚洲日本在线观看| 亚欧美中日韩视频| 欧美成人午夜视频| 国产精品拍天天在线| 亚洲国产精品综合| 欧美一区精品| 欧美日韩国产一区二区| 午夜精品久久久久久久99樱桃 | 狠狠色香婷婷久久亚洲精品| 一区二区三区久久精品| 欧美mv日韩mv国产网站app| 亚洲精品美女免费| 欧美三区在线视频| 亚洲免费网址| 国产九九精品视频| 亚洲一级网站| 欧美日韩精品综合| 99视频精品免费观看| 欧美精品亚洲二区| 在线欧美三区| 美乳少妇欧美精品| 亚洲精品一二区| 欧美日韩精品免费在线观看视频| 亚洲激情偷拍| 欧美特黄一级| 一本色道久久88亚洲综合88| 亚洲一区二区在线视频| 久久五月天婷婷| 免费观看成人网| 亚洲免费高清视频| 欧美一级免费视频| 欧美一级理论片| 亚洲第一精品夜夜躁人人躁| 国产日韩精品在线| 国产精品一区久久| 国产一区99| 久久精品一区蜜桃臀影院 | 国产精品色午夜在线观看| 国产欧美va欧美va香蕉在| 狠狠久久婷婷| 韩国欧美一区| 精品成人国产| 99精品欧美一区二区三区综合在线| 国产精品99久久久久久宅男| 久久综合九色综合欧美就去吻 | 亚洲韩国日本中文字幕| 狠狠色伊人亚洲综合网站色| 亚洲欧美激情一区| 欧美视频在线一区| 香蕉成人伊视频在线观看| 国产精品久久久久7777婷婷| 欧美一级播放| 99国产精品自拍| 国产一区二区日韩精品欧美精品| 免费亚洲一区| 亚洲午夜久久久久久久久电影院| 国产一区二区日韩精品欧美精品| 欧美韩日一区二区三区| 亚洲欧美精品在线观看| 亚洲国产高清自拍| 国产精品免费小视频| 免费不卡在线观看| 亚洲欧美日韩中文播放| 亚洲国产精品v| 国产三级精品三级| 欧美绝品在线观看成人午夜影视| 欧美主播一区二区三区美女 久久精品人| 91久久精品美女| 国内精品视频在线播放| 国产精品久久久久久久久免费 | 最新成人av网站| 国产亚洲欧美另类中文| 国产精品久久久久久久9999| 欧美11—12娇小xxxx| 久久爱91午夜羞羞| 亚洲欧美一区二区精品久久久| 亚洲人被黑人高潮完整版| 韩国一区二区三区美女美女秀| 国产精品三上| 国产精品久久久久久久久免费| 欧美日韩免费区域视频在线观看| 每日更新成人在线视频| 久久综合九色综合网站| 久久免费国产| 久久久久久久尹人综合网亚洲 | 久久精品导航| 久久久水蜜桃| 久久夜色精品| 久久综合亚州| 欧美大胆成人| 欧美另类99xxxxx| 欧美日韩视频免费播放| 女人色偷偷aa久久天堂| 欧美成人精品影院| 欧美人与性动交a欧美精品| 欧美日韩免费一区| 国产欧美精品va在线观看| 韩国欧美国产1区| 亚洲高清色综合| 你懂的视频一区二区| 亚洲欧美日韩视频二区| 久久亚洲精品伦理| 欧美日韩成人在线| 国产综合自拍| 午夜亚洲福利| 亚洲日本一区二区| 欧美淫片网站| 欧美日韩在线影院| 亚洲精品乱码久久久久久久久| 久久精品99无色码中文字幕| 欧美日韩成人在线观看| 136国产福利精品导航网址| 亚洲女女女同性video| 欧美综合国产| 麻豆久久精品| 国产精品成人一区| 精品999网站| 香蕉久久夜色精品国产| 久久五月天婷婷| 欧美日韩无遮挡| 一区二区三区在线免费观看| 一区二区三区精品久久久| 欧美一区二区播放| 欧美精品aa| 亚洲第一精品影视| 亚洲天堂久久| 欧美激情精品久久久久久蜜臀| 欧美日韩国产在线播放网站| 国产伦精品免费视频| 欧美日韩在线视频一区| 国产精品久久久久久久久免费樱桃| 一区二区三区国产精品| 亚洲欧洲精品一区二区三区| 国产麻豆日韩| 欧美日韩免费在线观看| 欧美区亚洲区| 欧美揉bbbbb揉bbbbb| 欧美日韩在线亚洲一区蜜芽| 国产精品女人毛片| 亚洲美女色禁图| 久久本道综合色狠狠五月| 欧美国产激情| 国产精品夫妻自拍| 国产一区二区主播在线 | 亚洲免费婷婷| 夜夜嗨av一区二区三区网站四季av | 国产精品推荐精品| 欧美1区3d| 久久精品国产第一区二区三区| 欧美一级大片在线观看| 欧美一区二区网站| 免费久久99精品国产自| 国产欧美日韩精品丝袜高跟鞋| 中文在线一区| 国产精品色网| 久久精品免费观看| 亚洲福利视频在线| 欧美日韩国产精品一区二区亚洲 | 欧美黄色成人网| 亚洲激情综合| 国产精品久久久久久超碰| 香蕉av777xxx色综合一区| 国产一区二区三区久久 | 欧美日韩免费在线观看| 亚洲午夜三级在线| 国产日韩精品一区二区浪潮av| 久久亚洲精品一区二区| 亚洲人成7777| 国产精品久久一区二区三区| 欧美一区二区免费观在线| 亚洲国产欧美一区二区三区久久| 欧美xxx在线观看| 一本色道久久综合一区| 国产视频精品xxxx| 欧美另类一区二区三区| 亚洲欧美日韩精品久久| 尤物99国产成人精品视频| 欧美日韩精品免费观看| 久久精品视频在线看| 一区二区不卡在线视频 午夜欧美不卡' | 日韩一级精品| 国产日韩一区二区三区在线| 欧美激情中文字幕在线| 欧美在线观看一二区| 亚洲精品在线免费| 国产日韩欧美视频在线| 欧美亚州韩日在线看免费版国语版| 久久久久欧美精品| 亚洲欧美成人在线| 99在线观看免费视频精品观看| 激情综合久久|