<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 題目 ### JS 異步解決方案的發展歷程以及優缺點 ### 1. 回調函數(callback) ~~~js setTimeout(() => { // callback 函數體 }, 1000) ~~~ **缺點:回調地獄,不能用 try catch 捕獲錯誤,不能 return** 回調地獄的根本問題在于: * 缺乏順序性: 回調地獄導致的調試困難,和大腦的思維方式不符 * 嵌套函數存在耦合性,一旦有所改動,就會牽一發而動全身,即(**控制反轉**) * 嵌套函數過多的多話,很難處理錯誤 ~~~js ajax('XXX1', () => { // callback 函數體 ajax('XXX2', () => { // callback 函數體 ajax('XXX3', () => { // callback 函數體 }) }) }) ~~~ **優點:解決了同步的問題**(只要有一個任務耗時很長,后面的任務都必須排隊等著,會拖延整個程序的執行。) #### 2. Promise Promise就是為了解決callback的問題而產生的。 Promise 實現了鏈式調用,也就是說每次 then 后返回的都是一個全新 Promise,如果我們在 then 中 return ,return 的結果會被 Promise.resolve() 包裝 **優點:解決了回調地獄的問題** ~~~js ajax('XXX1') .then(res => { // 操作邏輯 return ajax('XXX2') }).then(res => { // 操作邏輯 return ajax('XXX3') }).then(res => { // 操作邏輯 }) ~~~ **缺點:無法取消 Promise ,錯誤需要通過回調函數來捕獲** #### 3. Generator **特點:可以控制函數的執行**,可以配合 co 函數庫使用 ~~~js function *fetch() { yield ajax('XXX1', () => {}) yield ajax('XXX2', () => {}) yield ajax('XXX3', () => {}) } let it = fetch() let result1 = it.next() let result2 = it.next() let result3 = it.next() ~~~ #### 4. Async/await async、await 是異步的終極解決方案 **優點是:代碼清晰,不用像 Promise 寫一大堆 then 鏈,處理了回調地獄的問題** **缺點:await 將異步代碼改造成同步代碼,如果多個異步操作沒有依賴性而使用 await 會導致性能上的降低。** ~~~js async function test() { // 以下代碼沒有依賴性的話,完全可以使用 Promise.all 的方式 // 如果有依賴性的話,其實就是解決回調地獄的例子了 await fetch('XXX1') await fetch('XXX2') await fetch('XXX3') } ~~~ 下面來看一個使用`await`的例子: ~~~js let a = 0 let b = async () => { a = a + await 10 console.log('2', a) // -> '2' 10 } b() a++ console.log('1', a) // -> '1' 1 ~~~ 對于以上代碼你可能會有疑惑,讓我來解釋下原因 * 首先函數`b`先執行,在執行到`await 10`之前變量`a`還是 0,因為`await`內部實現了`generator`,**`generator`會保留堆棧中東西,所以這時候`a = 0`被保存了下來** * 因為`await`是異步操作,后來的表達式不返回`Promise`的話,就會包裝成`Promise.reslove(返回值)`,然后會去執行函數外的同步代碼 * 同步代碼執行完畢后開始執行異步代碼,將保存下來的值拿出來使用,這時候`a = 0 + 10` 上述解釋中提到了`await`內部實現了`generator`,其實`await`就是`generator`加上`Promise`的語法糖,且內部實現了自動執行`generator`。如果你熟悉 co 的話,其實自己就可以實現這樣的語法糖。 ## 摘自 [ 第 12 題:JS 異步解決方案的發展歷程以及優缺點](https://www.muyiy.cn/question/async/12.html)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看