<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之旅 廣告
                # 神奇的co * [co是什么?](https://i5ting.github.io/wechat-dev-with-nodejs/async/co.html#co是什么) * [源碼解析](https://i5ting.github.io/wechat-dev-with-nodejs/async/co.html#源碼解析) * [co引出的“血案”](https://i5ting.github.io/wechat-dev-with-nodejs/async/co.html#co引出的血案) ## co是什么? [https://github.com/tj/co](https://github.com/tj/co) > 官方說:The ultimate generator based flow-control goodness for nodejs (supports thunks, promises, etc) 我的解釋 * 是generator的執行器 * 可是使用generator里的Yieldable支持的所有形式(supports thunks, promises, etc) * 返回的結果是promise 那么它的用途就很明顯了 * 所有出現generator的地方它都可以出現 * 在以后的async/await里await后面可以接promise ## 源碼解析 co@4.6版本不到240行代碼,整體來說,還算比較簡單。但并不容易閱讀 ~~~ // 核心代碼 function co(gen) { // 緩存this var ctx = this; var args = slice.call(arguments, 1) // we wrap everything in a promise to avoid promise chaining, // which leads to memory leak errors. // see https://github.com/tj/co/issues/180 // 重點,co的返回值是Promise對象。為什么可以then和catch的根源 return new Promise(function(resolve, reject) { // 如果你懂Promise規范,就知道這是解決狀態回調,這是首次調用 onFulfilled(); /** * @param {Mixed} res * @return {Promise} * @api private */ function onFulfilled(res) { var ret; try { ret = gen.next(res); } catch (e) { return reject(e); } next(ret); } /** * @param {Error} err * @return {Promise} * @api private */ // 如果你懂Promise規范,就知道這是拒絕狀態回調 function onRejected(err) { var ret; try { ret = gen.throw(err); } catch (e) { return reject(e); } next(ret); } // generator執行器 // 如果ret.done,返回ret.value // 否則, function next(ret) { // 如果執行完成,直接調用resolve把promise置為成功狀態 if (ret.done) return resolve(ret.value); // 把yield的值轉換成promise // 支持 promise,generator,generatorFunction,array,object // toPromise的實現可以先不管,只要知道是轉換成promise就行了 var value = toPromise.call(ctx, ret.value); // 成功轉換就可以直接給新的promise添加onFulfilled, onRejected。當新的promise狀態變成結束態(成功或失敗)。就會調用對應的回調。整個next鏈路就執行下去了。 // 為什么generator可以無限的next下去呢? // return value.then(onFulfilled, onRejected);意味著,又要執行onFulfilled了 // onFulfilled里調用next(ret); if (value && isPromise(value)) return value.then(onFulfilled, onRejected); // 如果以上情況都沒發生,報錯 return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"')); } }); } ~~~ 讀此源碼要點 * 必須深刻理解Promise實現,知道構造函數里的onFulfilled和onRejected是什么意思 * 必須了解generator的執行機制,理解迭代器里的next以及next的返回對象{value:'',done: true} 核心代碼入口是onFulfilled,無論如何第一次的next(ret)是一定要執行的,因為generator必須要next()一下的。 所以next(ret)一定是重點,而且我們看onFulfilled和onRejected里都調用它,也就是所有的邏輯都會丟在這個next(ret)方法里。它實際上是一個狀態機的簡單實現。 ~~~ // generator執行器 // 如果ret.done,返回ret.value // 否則, function next(ret) { // 如果執行完成,直接調用resolve把promise置為成功狀態 if (ret.done) return resolve(ret.value); // 把yield的值轉換成promise // 支持 promise,generator,generatorFunction,array,object // toPromise的實現可以先不管,只要知道是轉換成promise就行了 var value = toPromise.call(ctx, ret.value); // 成功轉換就可以直接給新的promise添加onFulfilled, onRejected。當新的promise狀態變成結束態(成功或失敗)。就會調用對應的回調。整個next鏈路就執行下去了。 // 為什么generator可以無限的next下去呢? // return value.then(onFulfilled, onRejected);意味著,又要執行onFulfilled了 // onFulfilled里調用next(ret); if (value && isPromise(value)) return value.then(onFulfilled, onRejected); // 如果以上情況都沒發生,報錯 return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"')); } ~~~ 情景1: 狀態完成 ~~~ // 如果執行完成,直接調用resolve把promise置為成功狀態 if (ret.done) return resolve(ret.value); ~~~ 情景2: next,跳回onFulfilled,遞歸 ~~~ // 成功轉換就可以直接給新的promise添加onFulfilled, onRejected。當新的promise狀態變成結束態(成功或失敗)。就會調用對應的回調。整個next鏈路就執行下去了。 // 為什么generator可以無限的next下去呢? // return value.then(onFulfilled, onRejected);意味著,又要執行onFulfilled了 // onFulfilled里調用next(ret); if (value && isPromise(value)) return value.then(onFulfilled, onRejected); ~~~ 情景3: 捕獲異常 ~~~ // 如果以上情況都沒發生,報錯 return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, ' + 'but the following object was passed: "' + String(ret.value) + '"')); ~~~ 以上是核心代碼說明。之前我們講了co實際有2種api,有參數和無參數的,很明顯以上是無參數的generator執行器,那么有參數的wrap呢? ~~~ // 為有參數的generator調用,提供簡單包裝 co.wrap = function (fn) { createPromise.__generatorFunction__ = fn; return createPromise; function createPromise() { // 重點,把arguments給fn當參數。 // call和apply是常規js api return co.call(this, fn.apply(this, arguments)); } }; ~~~ 通過call和apply組合使用,知識點比較簡單,但這樣用還是挺巧妙的。 其他的就基本是工具類了,其實也挺有意思的,自己看吧 ## co引出的“血案” ES6的Generator本意是為了計算而設計的迭代器,但tj覺得它可以用于流程控制,于是就有了co,co的歷史可以說經歷了目前所有的流程控制方案,而且由于支持Generator和yield就導致yieldable。 實際上co和Generator是把雙刃劍,給了我們強大便利的同時,也增加了非常多的概念,可能是過渡性的,也可能是過時的。 可是,你真的需要了解這么多么?從學習的角度,當然是多多意義,如果從實用的角度看,你可能不需要。 存在即合理,那么我們就看看這“血案”吧: * 學習ES6的Generator * 了解ES6的迭代器和迭代器相關的2種協議,了解for-of * 了解co和co的2種用法,源碼 * 了解yieldable 5種(包括不常用Thunk) * 如果是koa,還需要了解convert和compose
                  <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>

                              哎呀哎呀视频在线观看