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

JavaScript 異步編程指南 - 如何用異步任務解決遞歸棧溢出?

開發 前端
在編程中使用遞歸,如果沒有控制好代碼的執行邊界或過多層級的遞歸調用,就會造成棧溢出錯誤,就像下面展示的這段錯誤堆棧。

 [[432656]]

在編程中使用遞歸,如果沒有控制好代碼的執行邊界或過多層級的遞歸調用,就會造成棧溢出錯誤,就像下面展示的這段錯誤堆棧。

 

  1. RangeError: Maximum call stack size exceeded 
  2.     at fn (/xxx/test.js:2:3) 
  3.     at fn (/xxx/test.js:7:10) 

為什么遞歸會造成堆棧溢出?

函數運行會有一個執行棧,每次調用會做入棧操作,保存一些局部變量、函數參數、當前程序的運行狀態等,這些信息都會保存在??臻g里,而??臻g的存儲是一段連續的內存地址,有大小限制。

以下是一段遞歸調用的簡單示例。

 

  1. function fn(i) { 
  2.   i--; 
  3.   if (i < 1) { 
  4.     return
  5.   } 
  6.   return fn(i); 
  7. fn(20000); 

以下通過 gif 動圖展示了上述代碼的執行過程,當在主線程上調用 fn 函數后,不斷的做壓棧操作,而棧空間也在不斷的增加,直到達到最大的??臻g限制,程序報錯 “Maximum call stack size exceeded”。

 

 

圖片

javascript-recursion-stack-overflow (1).gif

 

使用異步解決棧溢出問題解

決遞歸造成的棧溢出問題,一種方法是可以使用 JavaScript 中的異步任務,也是借助了事件循環機制。宏任務有 setTimeout、Node.js 環境下的 setImmediate,微任務有 Promise、queueMicrotask。

 

修改代碼,在 setTimeout 函數里遞歸調用。

 

  1. function fn(i) { 
  2.   i--; 
  3.   if (i < 1) { 
  4.     return
  5.   } 
  6.  
  7.   setTimeout(function() { 
  8.     fn(i); 
  9.   }, 0); 
  10.  
  11. fn(20000); 

運行效果如下所示:

 

 

圖片

javascript-async-recursion.gif

 

 

當首次調用 fn(2000) 時,創建一個調用棧,函數內部調用 setTimeout 函數后會立即返回,當前的調用棧就結束了,傳入的回調 **function() { fn(i) }** 還沒有執行,主線程不會在這里等待,也不會形成層層嵌套的調用鏈。

定時器函數由宿主環境實現,當將來的某個時間點計時器時間到達后,宿主環境會將 timer 函數封裝為一個事件放入 “任務隊列” 中,事件循環檢測到任務隊列有可執行的任務,就拿出來執行,之后再次調用 fn(i) 創建新的調用棧,反復循環。

還可以通過微任務實現,微任務有個缺點是當調度大量的微任務時雖然不會導致調用棧溢出,但也會導致和同步任務相同的性能缺陷,后面的任務得不到執行,瀏覽器的渲染工作也會被阻止,直到所有的微任務執行完畢。

總結

這個問題通過結合異步任務來解決遞歸造成的棧溢出問題,也可以做為事件循環的一個例子來學習,更好的掌握同步任務、異步之間的調度關系。

在程序中使用遞歸還是要謹慎的,若控制不好邊界,很容易造成 “棧溢出”。除了改為異步任務調用外,還可將遞歸改為循環迭代、尾遞歸優化等。

責任編輯:華軒 來源: 編程界
相關推薦

2021-06-28 08:10:59

JavaScript異步編程

2021-06-06 19:51:07

JavaScript異步編程

2020-10-15 13:29:57

javascript

2015-04-22 10:50:18

JavascriptJavascript異

2014-05-23 10:12:20

Javascript異步編程

2017-07-13 12:12:19

前端JavaScript異步編程

2016-09-07 20:43:36

Javascript異步編程

2021-06-02 09:01:19

JavaScript 前端異步編程

2011-11-11 15:47:22

JavaScript

2013-04-01 15:38:54

異步編程異步編程模型

2021-12-10 07:47:30

Javascript異步編程

2023-11-03 14:32:38

2023-12-04 13:22:00

JavaScript異步編程

2011-11-10 10:23:56

Jscex

2021-10-22 08:29:14

JavaScript事件循環

2021-06-15 07:10:14

JavaScript異步編程

2011-07-27 14:10:43

javascript

2022-10-31 09:00:24

Promise數組參數

2013-04-01 15:25:41

異步編程異步EMP

2021-10-15 09:56:10

JavaScript異步編程
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 在线第一页| 在线免费观看视频你懂的 | 在线免费观看毛片 | 国产精品伦一区二区三级视频 | 成人久久久 | 亚洲视频免费观看 | 亚洲精品一区中文字幕 | 欧美一区二区三区视频 | 日韩在线资源 | 亚洲国产情侣自拍 | www.五月婷婷.com | 日本精品视频在线观看 | 91在线精品一区二区 | 亚洲天天| 在线观看视频亚洲 | 亚洲aⅴ| 国产网站在线免费观看 | 黄色视频a级毛片 | 国产一区免费 | 久久最新 | 国产精品欧美一区二区三区 | 午夜国产精品视频 | 一区二区在线看 | 日韩成人久久 | 久久99精品久久久久久琪琪 | 国产精品久久久久久久久久久久久 | 狠狠插狠狠操 | 中文字幕在线观看精品 | 99免费在线视频 | 亚洲欧美一区二区三区国产精品 | 中文天堂在线一区 | 本道综合精品 | 欧美日韩一区二区三区在线观看 | 在线视频 亚洲 | 日韩一区二区在线视频 | 亚洲xxxxx| 精品亚洲一区二区三区 | 精品免费视频 | 国产精品视频一 | 在线视频 亚洲 | 亚洲第一成人影院 |