<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>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                異步編程有很多特有的代碼設計模式,為了實現同樣的功能,使用同步方式和異步方式編寫的代碼會有很大差異。以下分別介紹一些常見的模式。 ## 函數返回值 使用一個函數的輸出作為另一個函數的輸入是很常見的需求,在同步方式下一般按以下方式編寫代碼: ~~~ var output = fn1(fn2('input')); // Do something. ~~~ 而在異步方式下,由于函數執行結果不是通過返回值,而是通過回調函數傳遞,因此一般按以下方式編寫代碼: ~~~ fn2('input', function (output2) { fn1(output2, function (output1) { // Do something. }); }); ~~~ 可以看到,這種方式就是一個回調函數套一個回調函多,套得太多了很容易寫出`>`形狀的代碼。 ## 遍歷數組 在遍歷數組時,使用某個函數依次對數據成員做一些處理也是常見的需求。如果函數是同步執行的,一般就會寫出以下代碼: ~~~ var len = arr.length, i = 0; for (; i < len; ++i) { arr[i] = sync(arr[i]); } // All array items have processed. ~~~ 如果函數是異步執行的,以上代碼就無法保證循環結束后所有數組成員都處理完畢了。如果數組成員必須一個接一個串行處理,則一般按照以下方式編寫異步代碼: ~~~ (function next(i, len, callback) { if (i < len) { async(arr[i], function (value) { arr[i] = value; next(i + 1, len, callback); }); } else { callback(); } }(0, arr.length, function () { // All array items have processed. })); ~~~ 可以看到,以上代碼在異步函數執行一次并返回執行結果后才傳入下一個數組成員并開始下一輪執行,直到所有數組成員處理完畢后,通過回調的方式觸發后續代碼的執行。 如果數組成員可以并行處理,但后續代碼仍然需要所有數組成員處理完畢后才能執行的話,則異步代碼會調整成以下形式: ~~~ (function (i, len, count, callback) { for (; i < len; ++i) { (function (i) { async(arr[i], function (value) { arr[i] = value; if (++count === len) { callback(); } }); }(i)); } }(0, arr.length, 0, function () { // All array items have processed. })); ~~~ 可以看到,與異步串行遍歷的版本相比,以上代碼并行處理所有數組成員,并通過計數器變量來判斷什么時候所有數組成員都處理完畢了。 ## 異常處理 JS自身提供的異常捕獲和處理機制——`try..catch..`,只能用于同步執行的代碼。以下是一個例子。 ~~~ function sync(fn) { return fn(); } try { sync(null); // Do something. } catch (err) { console.log('Error: %s', err.message); } -- Console ------------------------------ Error: object is not a function ~~~ 可以看到,異常會沿著代碼執行路徑一直冒泡,直到遇到第一個`try`語句時被捕獲住。但由于異步函數會打斷代碼執行路徑,異步函數執行過程中以及執行之后產生的異常冒泡到執行路徑被打斷的位置時,如果一直沒有遇到`try`語句,就作為一個全局異常拋出。以下是一個例子。 ~~~ function async(fn, callback) { // Code execution path breaks here. setTimeout(function () { callback(fn()); }, 0); } try { async(null, function (data) { // Do something. }); } catch (err) { console.log('Error: %s', err.message); } -- Console ------------------------------ /home/user/test.js:4 callback(fn()); ^ TypeError: object is not a function at null._onTimeout (/home/user/test.js:4:13) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15) ~~~ 因為代碼執行路徑被打斷了,我們就需要在異常冒泡到斷點之前用`try`語句把異常捕獲住,并通過回調函數傳遞被捕獲的異常。于是我們可以像下邊這樣改造上邊的例子。 ~~~ function async(fn, callback) { // Code execution path breaks here. setTimeout(function () { try { callback(null, fn()); } catch (err) { callback(err); } }, 0); } async(null, function (err, data) { if (err) { console.log('Error: %s', err.message); } else { // Do something. } }); -- Console ------------------------------ Error: object is not a function ~~~ 可以看到,異常再次被捕獲住了。在NodeJS中,幾乎所有異步API都按照以上方式設計,回調函數中第一個參數都是`err`。因此我們在編寫自己的異步函數時,也可以按照這種方式來處理異常,與NodeJS的設計風格保持一致。 有了異常處理方式后,我們接著可以想一想一般我們是怎么寫代碼的。基本上,我們的代碼都是做一些事情,然后調用一個函數,然后再做一些事情,然后再調用一個函數,如此循環。如果我們寫的是同步代碼,只需要在代碼入口點寫一個`try`語句就能捕獲所有冒泡上來的異常,示例如下。 ~~~ function main() { // Do something. syncA(); // Do something. syncB(); // Do something. syncC(); } try { main(); } catch (err) { // Deal with exception. } ~~~ 但是,如果我們寫的是異步代碼,就只有呵呵了。由于每次異步函數調用都會打斷代碼執行路徑,只能通過回調函數來傳遞異常,于是我們就需要在每個回調函數里判斷是否有異常發生,于是只用三次異步函數調用,就會產生下邊這種代碼。 ~~~ function main(callback) { // Do something. asyncA(function (err, data) { if (err) { callback(err); } else { // Do something asyncB(function (err, data) { if (err) { callback(err); } else { // Do something asyncC(function (err, data) { if (err) { callback(err); } else { // Do something callback(null); } }); } }); } }); } main(function (err) { if (err) { // Deal with exception. } }); ~~~ 可以看到,回調函數已經讓代碼變得復雜了,而異步方式下對異常的處理更加劇了代碼的復雜度。如果NodeJS的最大賣點最后變成這個樣子,那就沒人愿意用NodeJS了,因此接下來會介紹NodeJS提供的一些解決方案。
                  <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>

                              哎呀哎呀视频在线观看