成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

React 核心團隊成員解釋“代數效應與 React”

新聞 前端
React核心團隊成員Sebastian Markbåge[1](React Hooks的發明者)曾說:我們在React中做的就是踐行代數效應(Algebraic Effects)。

 React核心團隊成員Sebastian Markbåge[1](React Hooks的發明者)曾說:我們在React中做的就是踐行代數效應(Algebraic Effects)。

那么,代數效應是什么呢?它和React有什么關系呢。

[[345619]]

什么是代數效應

代數效應是函數式編程中的一個概念,用于將副作用從函數調用中分離。

接下來我們用虛構的語法來解釋。

假設我們有一個函數getTotalPicNum,傳入2個用戶名稱后,分別查找該用戶在平臺保存的圖片數量,最后將圖片數量相加后返回。

  1. function getTotalPicNum(user1, user2) { 
  2.  
  3.   const num1 = getPicNum(user1); 
  4.  
  5.   const num2 = getPicNum(user2); 
  6.  
  7.   return picNum1 + picNum2; 
  8.  

在getTotalPicNum中,我們不關注getPicNum的實現,只在乎“獲取到兩個數字后將他們相加的結果返回”這一過程。

接下來我們來實現getPicNum。

"用戶在平臺保存的圖片數量"是保存在服務器中的。所以,為了獲取該值,我們需要發起異步請求。

為了盡量保持getTotalPicNum的調用方式不變,我們首先想到了使用async await:

  1. async function getTotalPicNum(user1, user2) { 
  2.  
  3.   const num1 = await getPicNum(user1); 
  4.  
  5.   const num2 = await getPicNum(user2); 
  6.  
  7.   return picNum1 + picNum2; 
  8.  

但是,async await是有傳染性的 —— 當一個函數變為async后,這意味著調用他的函數也需要是async,這破壞了getTotalPicNum的同步特性。

有沒有什么辦法能保持getTotalPicNum保持現有調用方式不變的情況下實現異步請求呢?

沒有。不過我們可以虛構一個。

我們虛構一個類似try...catch的語法 —— try...handle與兩個操作符perform、resume。

  1. function getPicNum(name) { 
  2.  
  3.   const picNum = perform name; 
  4.  
  5.   return picNum; 
  6.  
  7.  
  8. try { 
  9.  
  10.   getTotalPicNum('kaSong''xiaoMing'); 
  11.  
  12. } handle (who) { 
  13.  
  14.   switch (who) { 
  15.  
  16.     case 'kaSong'
  17.  
  18.       resume with 230
  19.  
  20.     case 'xiaoMing'
  21.  
  22.       resume with 122
  23.  
  24.     default
  25.  
  26.       resume with 0
  27.  
  28.   } 
  29.  

當執行到getTotalPicNum內部的getPicNum方法時,會執行perform name。

此時函數調用棧會從getPicNum方法內跳出,被最近一個try...handle捕獲。類似throw Error后被最近一個try...catch捕獲。

類似throw Error后Error會作為catch的參數,perform name后name會作為handle的參數。

與try...catch最大的不同在于:當Error被catch捕獲后,之前的調用棧就銷毀了。而handle執行resume后會回到之前perform的調用棧。

對于case 'kaSong',執行完resume with 230;后調用棧會回到getPicNum,此時picNum === 230

再次申明,try...handle的語法是虛構的,只是為了演示代數效應的思想。

總結一下:代數效應能夠將副作用(例子中為請求圖片數量)從函數邏輯中分離,使函數關注點保持純粹。

并且,從例子中可以看出,perform resume不需要區分同步異步。

代數效應在React中的應用

那么代數效應與React有什么關系呢?最明顯的例子就是Hooks。

對于類似useState、useReducer、useRef這樣的Hook,我們不需要關注FunctionComponent的state在Hook中是如何保存的,React會為我們處理。

我們只需要假設useState返回的是我們想要的state,并編寫業務邏輯就行。

  1. function App() { 
  2.  
  3.   const [num, updateNum] = useState(0); 
  4.  
  5.    
  6.  
  7.   return ( 
  8.  
  9.     <button onClick={() => updateNum(num => num + 1)}>{num}</button>   
  10.  
  11.   ) 
  12.  

如果這個例子還不夠明顯,可以看看官方的Suspense Demo[2]

在Demo中ProfileDetails用于展示用戶名稱。而用戶名稱是異步請求的。

但是Demo中完全是同步的寫法。

  1. function ProfileDetails() { 
  2.  
  3.   const user = resource.user.read(); 
  4.  
  5.   return <h1>{user.name}</h1>; 
  6.  

代數效應與Generator

從React15到React16,協調器(Reconciler)重構的一大目的是:將老的同步更新的架構變為異步可中斷更新。

異步可中斷更新可以理解為:更新在執行過程中可能會被打斷(瀏覽器時間分片用盡或有更高優任務插隊),當可以繼續執行時恢復之前執行的中間狀態。

這就是代數效應中try...handle的作用。

其實,瀏覽器原生就支持類似的實現,這就是Generator。

但是Generator的一些缺陷使React團隊放棄了他:

類似async,Generator也是傳染性的,使用了Generator則上下文的其他函數也需要作出改變。這樣心智負擔比較重。

Generator執行的中間狀態是上下文關聯的。

考慮如下例子:

  1. function* doWork(A, B, C) { 
  2.  
  3.   var x = doExpensiveWorkA(A); 
  4.  
  5.   yield; 
  6.  
  7.   var y = x + doExpensiveWorkB(B); 
  8.  
  9.   yield; 
  10.  
  11.   var z = y + doExpensiveWorkC(C); 
  12.  
  13.   return z; 
  14.  

每當瀏覽器有空閑時間都會依次執行其中一個doExpensiveWork,當時間用盡則會中斷,當再次恢復時會從中斷位置繼續執行。

只考慮“單一優先級任務的中斷與繼續”情況下Generator可以很好的實現異步可中斷更新。

但是當我們考慮“高優先級任務插隊”的情況,如果此時已經完成doExpensiveWorkA與doExpensiveWorkB計算出x與y。

此時B組件接收到一個高優更新,由于Generator執行的中間狀態是上下文關聯的的,所以重新計算y時無法復用之前已經計算出的x,需要重新計算。

如果通過全局變量保存之前執行的中間狀態,又會引入新的復雜度。

更詳細的解釋可以參考這個issue[3]

基于這些原因,React沒有采用Generator實現協調器。

代數效應與Fiber

Fiber并不是計算機術語中的新名詞,他的中文翻譯叫做纖程,與進程(Process)、線程(Thread)、協程(Coroutine)同為程序執行過程。

在很多文章中將纖程理解為協程的一種實現。在JS中,協程的實現便是Generator。

所以,我們可以將纖程(Fiber)、協程(Generator)理解為代數效應思想在JS中的體現。

React Fiber可以理解為:

React內部實現的一套狀態更新機制。支持任務不同優先級,可中斷與恢復,并且恢復后可以復用之前的中間狀態。

其中每個任務更新單元為React Element對應的Fiber節點。

 

責任編輯:張燕妮 來源: 程序員的那些事
相關推薦

2023-07-22 00:33:07

React團隊數據

2021-05-24 06:00:20

ReactJSXJS

2020-01-07 15:40:43

React前端技術準則

2023-02-02 08:41:14

React團隊Vite

2023-03-24 12:34:56

2022-06-27 07:23:20

React?并發

2022-07-06 15:07:47

React開發

2020-11-24 07:48:32

React

2015-10-10 16:02:36

React NativAndroid

2022-05-06 07:31:01

useEventReactHook

2022-08-22 16:23:11

React特性

2022-10-29 08:55:19

頁面react

2023-05-31 07:29:46

2022-04-15 08:07:21

ReactDiff算法

2021-12-16 06:21:16

React組件前端

2023-03-19 11:42:19

React新官方文檔

2021-10-15 14:28:30

React 組件渲染

2020-10-23 09:26:57

React-Redux

2021-02-02 08:11:50

火焰圖組件技術

2023-07-03 07:51:47

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 五月精品视频 | 奇米影视首页 | 91久久精品一区二区三区 | 午夜精品久久久久久久久久久久 | 日韩在线中文字幕 | 亚洲国产精品精华素 | 网站黄色在线 | 一区二区福利视频 | 欧美大片黄 | 伊人久久综合 | 欧美一级免费看 | 亚洲精品国产成人 | 久亚州在线播放 | av网站在线播放 | 欧美精品区 | 国产日产久久高清欧美一区 | 中文天堂在线观看 | 欧美三级视频 | 国产一区二区精品 | 欧美日韩三级 | 成人av免费 | 日韩欧美手机在线 | 91av在线影院 | 欧美最猛性xxxxx亚洲精品 | 男人天堂网址 | 久久亚洲一区二区三区四区 | 亚洲精品久 | 成人久久久久久久久 | 亚洲国产偷 | 精品视频一二区 | 欧美人妇做爰xxxⅹ性高电影 | 久久久久久国产精品免费免费男同 | 国产三级国产精品 | 亚洲天堂日韩精品 | 欧美日一区 | 欧美精品啪啪 | 欧美成人黄色小说 | 欧美视频精品 | 国产 欧美 日韩 一区 | 久久一级免费视频 | 国产九九精品 |