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

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                如果你使用過其他的Promise實現類庫的話,可能見過用`done`代替`then`的例子。 這些類庫都提供了?`Promise.prototype.done`?方法,使用起來也和?`then`?一樣,但是這個方法并不會返回promise對象。 雖然?[ES6 Promises](http://liubin.github.io/promises-book/#es6-promises)和[Promises/A+](http://liubin.github.io/promises-book/#promises-aplus)等在設計上并沒有對`Promise.prototype.done`?做出任何規定,但是很多實現類庫都提供了該方法的實現。 在本小節中,我們將會學習什么是?`Promise.prototype.done`?,以及為什么很多類庫都提供了對該方法的支持。 ## 4.6.1\. 使用done的代碼示例 看一下實際使用done的代碼的例子的話,應該就非常容易理解?`done`?方法的行為了。 promise-done-example.js ~~~ if (typeof Promise.prototype.done === 'undefined') { Promise.prototype.done = function (onFulfilled, onRejected) { this.then(onFulfilled, onRejected).catch(function (error) { setTimeout(function () { throw error; }, 0); }); }; } var promise = Promise.resolve(); promise.done(function () { JSON.parse('this is not json'); // => SyntaxError: JSON.parse }); // => 請打開瀏覽器的開發者工具中的控制臺窗口看一下 ~~~ 在前面我們已經說過,promise設計規格并沒有對?`Promise.prototype.done`做出任何規定,因此在使用的時候,你可以使用已有類庫提供的實現,也可以自己去實現。 我們會在后面講述如何去自己實現,首先我們這里先對使用?`then`?和使用?`done`這兩種方式進行一下比較。 使用then的場景 ~~~ var promise = Promise.resolve(); promise.then(function () { JSON.parse("this is not json"); }).catch(function (error) { console.error(error);// => "SyntaxError: JSON.parse" }); ~~~ 從上面我們可以看出,兩者之間有以下不同點。 * `done`?并不返回promise對象 * 也就是說,在done之后不能使用?`catch`?等方法組成方法鏈 * `done`?中發生的異常會被直接拋給外面 * 也就是說,不會進行Promise的錯誤處理(Error Handling) 由于`done`?不會返回promise對象,所以我們不難理解它只能出現在一個方法鏈的最后。 此外,我們已經介紹過了Promise具有強大的錯誤處理機制,而`done`則會在函數中跳過錯誤處理,直接拋出異常。 為什么很多類庫都提供了這個和Promise功能相矛盾的函數呢?看一下下面Promise處理失敗的例子,也許我們多少就能理解其中原因了吧。 ## 4.6.2\. 消失的錯誤 Promise雖然具備了強大的錯誤處理機制,但是(調試工具不能順利運行的時候)這個功能會導致人為錯誤(human error)更加復雜,這也是它的一個缺點。 也許你還記得,我們在?[then or catch?](http://liubin.github.io/promises-book/#then-or-catch)?中也看到了類似的內容。 像下面那樣,我們看一個能返回promise對象的函數。 json-promise.js ~~~ function JSONPromise(value) { return new Promise(function (resolve) { resolve(JSON.parse(value)); }); } ~~~ 這個函數將接收到的參數傳遞給?`JSON.parse`?,并返回一個基于`JSON.parse`的promise對象。 我們可以像下面那樣使用這個Promise函數,由于?`JSON.parse`?會解析失敗并拋出一個異常,該異常會被?`catch`?捕獲。 ~~~ function JSONPromise(value) { return new Promise(function (resolve) { resolve(JSON.parse(value)); }); } // 運行示例 var string = "非合法json編碼字符串"; JSONPromise(string).then(function (object) { console.log(object); }).catch(function(error){ // => JSON.parse拋出異常時 console.error(error); }); ~~~ 如果這個解析失敗的異常被正常捕獲的話則沒什么問題,但是如果編碼時忘記了處理該異常,一旦出現異常,那么查找異常發生的源頭將會變得非常棘手,這就是使用promise需要注意的一面。 忘記了使用catch進行異常處理的的例子 ~~~ var string = "非合法json編碼字符串"; JSONPromise(string).then(function (object) { console.log(object); }); // 雖然拋出了異常,但是沒有對該異常進行處理 ~~~ 如果是`JSON.parse`?這樣比較好找的例子還算好說,如果是拼寫錯誤的話,那么發生了Syntax Error錯誤的話將會非常麻煩。 typo錯誤 ~~~ var string = "{}"; JSONPromise(string).then(function (object) { conosle.log(object);//存在conosle這個拼寫錯誤 }); ~~~ 這這個例子里,我們錯把?`console`?拼成了?`conosle`?,因此會發生如下錯誤。 > > > ReferenceError: conosle is not defined > > 但是,由于Promise的try-catch機制,這個問題可能會被內部消化掉。 如果在調用的時候每次都無遺漏的進行?`catch`?處理的話當然最好了,但是如果在實現的過程中出現了這個例子中的錯誤的話,那么進行錯誤排除的工作也會變得困難。 這種錯誤被內部消化的問題也被稱為?_unhandled rejection_?,從字面上看就是在Rejected時沒有找到相應處理的意思。 這種unhandled rejection錯誤到底有多難檢查,也依賴于Promise的實現。 比如?[ypromise](https://github.com/yahoo/ypromise)?在檢測到 unhandled rejection 錯誤的時候,會在控制臺上提示相應的信息。 > > > Promise rejected but no error handlers were registered to it > 另外,?[Bluebird](https://github.com/petkaantonov/bluebird)?在比較明顯的人為錯誤,即ReferenceError等錯誤的時候,會直接顯示到控制臺上。 > "Possibly unhandled ReferenceError. conosle is not defined > 原生(Native)的 Promise實現為了應對同樣問題,提供了GC-based unhandled rejection tracking功能。 該功能是在promise對象被垃圾回收器回收的時候,如果是unhandled rejection的話,則進行錯誤顯示的一種機制。 [Firefox](https://twitter.com/domenic/status/461154989856264192)?或?[Chrome](https://code.google.com/p/v8/issues/detail?id=3093)?的原生Promise都進行了部分實現。 ## 4.6.3\. done的實現 作為方法論,在Promise中?`done`?是怎么解決上面提到的錯誤被忽略呢? 其實它的方法很簡單直接,那就是必須要進行錯誤處理。 由于可以在 Promise上實現?`done`?方法,因此我們看看如何對?`Promise.prototype.done`?這個Promise的prototype進行擴展。 promise-prototype-done.js ~~~ "use strict"; if (typeof Promise.prototype.done === "undefined") { Promise.prototype.done = function (onFulfilled, onRejected) { this.then(onFulfilled, onRejected).catch(function (error) { setTimeout(function () { throw error; }, 0); }); }; } ~~~ 那么它是如何將異常拋到Promise的外面的呢?其實這里我們利用的是在setTimeout中使用throw方法,直接將異常拋給了外部。 setTimeout的回調函數中拋出異常 ~~~ try{ setTimeout(function callback() { throw new Error("error");//這個例外不會被捕獲 }, 0); }catch(error){ console.error(error); } ~~~ > 關于為什么異步的`callback`中拋出的異常不會被捕獲的原因,可以參考下面內容。 > * [JavaScript和異步錯誤處理 - Yahoo! JAPAN Tech Blog(日語博客)](http://techblog.yahoo.co.jp/programming/javascript_error/) 仔細看一下?[`Promise.prototype.done`](http://liubin.github.io/promises-book/#promise-prototype-done.js)的代碼,我們會發現這個函數什么也沒?`return`?。 也就是說,?`done`按照「Promise chain在這里將會中斷,如果出現了異常,直接拋到promise外面即可」的原則進行了處理。 如果實現和運行環境實現的比較完美的話,就可以進行?_unhandled rejection_?檢測,`done`也不一定是必須的了。 另外像本小節中的?[`Promise.prototype.done`](http://liubin.github.io/promises-book/#promise-prototype-done.js)一樣,`done`也可以在既有的Promise之上進行實現,也可以說它沒有進入到?[ES6 Promises](http://liubin.github.io/promises-book/#es6-promises)的設計規范之中。 > 本文中的?`Promise.prototype.done`?的實現方法參考了?[promisejs.org](https://www.promisejs.org/)?。 ## 4.6.4\. 總結 在本小節中,我們學習了?[Q](https://github.com/kriskowal/q/wiki/API-Reference#promisedoneonfulfilled-onrejected-onprogress)?、?[Bluebird](https://github.com/petkaantonov/bluebird)?和?[prfun](https://github.com/cscott/prfun#promisedone—undefined)?等Promise類庫提供的?`done`?的基礎和實現細節,以及`done`方法和?`then`?方法有什么區別等內容。 我們也學到了?`done`?有以下兩個特點。 * `done`?中出現的錯誤會被作為異常拋出 * 終結 Promise chain 和?[then or catch?](http://liubin.github.io/promises-book/#then-or-catch)?中說到的一樣,由Promise內部消化掉的錯誤,隨著調試工具或者類庫的改進,大多數情況下也許已經不是特別大的問題了。 此外,由于?`done`?不會有返回值,因此不能在它之后進行方法鏈的創建,為了實現Promise方法風格上的統一,我們也可以使用`done`方法。 [ES6 Promises](http://liubin.github.io/promises-book/#es6-promises)?本身提供的功能并不是特別多。 因此,我想很多時候可能需要我們自己進行擴展或者使用第三方類庫。 我們好不容易將異步處理統一采用Promise進行統一處理,但是如果做過頭了,也會將系統變得特別復雜,因此,保持風格的統一是Promise作為抽象對象非常重要的部分。 > 在?[Promises: The Extension Problem (part 4) | getiblog](http://blog.getify.com/promises-part-4/)?中,介紹了一些如何編寫Promise擴展程序的方法。 > * 擴展?`Promise.prototype`?的方法 > * 利用 Wrapper/Delegate 創建抽象層 > 此外,關于 Delegate 的詳細使用方法,也可以參考?[Chapter?28.?Subclassing Built-ins](http://speakingjs.com/es5/ch28.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>

                              哎呀哎呀视频在线观看