<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、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # Node.js Promise/a+實現 ## Node.js 內置promise說明 從0.12開始部分支持,到4.0支持絕大部分了。 ![Sdk](https://i5ting.github.io/wechat-dev-with-nodejs/async/img/sdk.png) 但性能比較低,所以一般是使用bluebird替換的。 ## Node.js的promise庫 Promise擴展類庫除了實現了Promise中定義的規范之外,還增加了自己獨自定義的功能。 按字母排序 | package | repo | alias | | --- | --- | --- | | [bluebird](https://www.npmjs.com/package/bluebird) | [petkaantonov/bluebird](https://github.com/petkaantonov/bluebird) | bb | | [es6-promise](https://www.npmjs.com/package/es6-promise) | [jakearchibald/es6-promise](https://github.com/jakearchibald/es6-promise) | | [es6-promise-polyfill](https://www.npmjs.com/package/es6-promise-polyfill)?[1](https://i5ting.github.io/wechat-dev-with-nodejs/async/nodejs.html#fn_1) | [lahmatiy/es6-promise-polyfill](https://github.com/lahmatiy/es6-promise-polyfill) | | [es6-promises](https://www.npmjs.com/package/es6-promises) | [Octane/Promise](https://github.com/Octane/Promise) | | [lie](https://www.npmjs.com/package/lie) | [calvinmetcalf/lie](https://github.com/calvinmetcalf/lie) | | [native-promise-only](https://www.npmjs.com/package/native-promise-only) | [getify/native-promise-only](https://github.com/getify/native-promise-only) | npo | | [promiscuous](https://www.npmjs.com/package/promiscuous) | [RubenVerborgh/promiscuous](https://github.com/RubenVerborgh/promiscuous) | | [promise](https://www.npmjs.com/package/promise) | [then/promise](https://github.com/then/promise) | then | | [promiz](https://www.npmjs.com/package/promiz) | [Zolmeister/promiz](https://github.com/Zolmeister/promiz) | | [q](https://www.npmjs.com/package/q) | [kriskowal/q](https://github.com/kriskowal/q) | | [rsvp](https://www.npmjs.com/package/rsvp) | [tildeio/rsvp.js](https://github.com/tildeio/rsvp.js) | | [vow](https://www.npmjs.com/package/vow) | [dfilatov/vow](https://github.com/dfilatov/vow) | | [when](https://www.npmjs.com/package/when) | [cujojs/when](https://github.com/cujojs/when) | w | > 1. based on es6-promise, so excluded from the registery by default[??](https://i5ting.github.io/wechat-dev-with-nodejs/async/nodejs.html#reffn_1 "Jump back to footnote [1] in the text.") Promise擴展類庫數量非常的多,我們只介紹其中兩個比較有名的類庫。 * [kriskowal/q](https://github.com/kriskowal/q) 類庫 Q 實現了 Promises 和 Deferreds 等規范。 它自2009年開始開發,還提供了面向Node.js的文件IO API Q-IO 等, 是一個在很多場景下都能用得到的類庫。 * [petkaantonov/bluebird](https://github.com/petkaantonov/bluebird) 這個類庫除了兼容 Promise 規范之外,還擴展了取消promise對象的運行,取得promise的運行進度,以及錯誤處理的擴展檢測等非常豐富的功能,此外它在實現上還在性能問題下了很大的功夫。 Q 和 Bluebird 這兩個類庫除了都能在瀏覽器里運行之外,充實的API reference也是其特征。由于Bluebird的性能比較好,所以我們一般用Bluebird的時候會比較多。 Q等文檔里詳細介紹了Q的Deferred和jQuery里的Deferred有哪些異同,以及要怎么進行遷移 Coming from jQuery 等都進行了詳細的說明。 Bluebird的文檔除了提供了使用Promise豐富的實現方式之外,還涉及到了在出現錯誤時的對應方法以及 Promise中的反模式 等內容。 這兩個類庫的文檔寫得都很友好,即使我們不使用這兩個類庫,閱讀一下它們的文檔也具有一定的參考價值。 ## 替換bluebird > tj: bluebird is MASSIVE, why not use v8's? bluebird是Node.js世界里性能最好的Promise/a+規范的實現模塊,api非常齊全,功能強大,是原生Promise外的不二選擇。 安裝bluebird模塊 ~~~ $ npm i -S bluebird ~~~ 見代碼`hellopromise-bb.js` ~~~ // callbacks to promise var fs = require("fs"); var Promise = require("bluebird"); function hello (file) { return new Promise(function(resolve, reject){ fs.readFile(file, (err, data) => { if (err) { reject(err); } else { resolve(data.toString()) } }); }); } hello('./package.json').then(function(data){ console.log('promise result = ' + data) }).catch(function(err) { console.log(err) }) ~~~ 它和之前的`hellopromise.js`執行結果是一模一樣的,只差一行代碼,即 ~~~ var Promise = require("bluebird"); ~~~ 由此可以看出,Node.js原生的Promise和bluebird的實現是兼容的。只要掌握其中任何一個,幾乎是0成本代價就可以學會。 這里用的是`var`來聲明`Promise`,主要目的是為了當前文件使用,如果是koa或express這樣的web項目里,使用全局替換呢? 其實也很簡單,使用global全局替換就好,在應用的入口文件app.js里 ~~~ global.Promise = require("bluebird"); ~~~ 性能會有明顯的提升。 > 另外八卦一下,node之前版本的promise是有內存泄漏的,而使用bluebird不會遇到這樣的坑 ## Promisification > Promisification means converting an existing promise-unaware API to a promise-returning API. 這里主要介紹一下bluebird的promisefy和promisifyAll promisifyAll更徹底,對類方法或者對象方法都可以進行promisify處理,是最簡單的包裹promisify的常用手段,比如 ~~~ var Promise = require("bluebird"); var fs = Promise.promisifyAll(require("fs")); fs.readFileAsync("./package.json", "utf8").then(function(contents) { console.log(contents); }).catch(function(e) { console.error(e.stack); }); ~~~ 再來個稍微復雜一些的,下面這個例子有abc 3個方法,每個都是普通函數,通過bluebird的promisifyAll讓他變成promise對象,繼而完成流程控制。 ~~~ var Promise = require("bluebird"); var obj = { a: function(){ console.log('a') }, b: function(){ console.log('b') }, c: function(){ console.log('c') } } Promise.promisifyAll(obj); obj.aAsync().then(obj.bAsync()).then(obj.cAsync()).catch(function(err){ console.log(err) }) ~~~ 是不是非常簡單? 危險常常來自便利處,大量的這樣promisifyAll,會不會有性能問題呢?error被bluebird包裹了,我們自己想定制呢? ## Promise的5個api ![](https://i5ting.github.io/wechat-dev-with-nodejs/async/img/promise-methods.png) 1)構造方法 語法 > new Promise( /*?executor?*/ function(resolve, reject) { ... } ); 所有Promise只能這樣創建,它的2個參數resolve和reject是唯一可以改變對象狀態的方法。 * resolve會讓狀態從pending切換到fulfilled * reject會讓狀態從pending切換到rejected(可選,不寫也不算錯) * Promise.prototype.then()可以當前操作的reject異常 * Promise.prototype.catch()可以捕獲全局的reject異常 備注:這里的resolve相當于Promise.resolve的別名,reject相當于Promise.reject的別名。 promise/api/a.js ~~~ new Promise(function(resolve){ resolve(1); }).then(function(value){ console.log('new Promise ' + value); }); Promise.resolve(1).then(function(value){ console.log('Promise.resolve ' + value); }); ~~~ 這2個示例resolve效果是一樣的,可以看出Promise.resolve是便捷用法 promise/api/b.js ~~~ var error = new Error('this is a error') new Promise(function(resolve, reject){ reject(error); }).catch(function(err){ console.log('new Promise ' + err); }); Promise.reject(error).catch(function(err){ console.log('Promise.resolve ' + err); }); ~~~ 這2個示例reject效果是一樣的,可以看出Promise.reject是便捷用法 既然resolve和reject都有別名,那么我們能不能不適用構造函數,直接使用便捷用法呢?答案是不可以的,具體如下,見promise/api/c.js ~~~ // 以下做法是錯誤的 new Promise(function(){ return Promise.resolve(1) }).then(function(value){ console.log('Promise.resolve 1 ' + value); }); ~~~ 可能有的庫會實現,但Node.js的原生Promise是不支持這樣的寫法的。 想便捷的話,一般采用下面這樣的方法 promise/api/d.js ~~~ // 以下做法是正確的的 function hello(i){ return Promise.resolve(i) } hello(1).then(function(value){ console.log('Promise.resolve 1 ' + value); }); ~~~ 這種寫法可行原因是,Promise.resolve返回的是Promise對象,相當于`new Promise(resolve, reject)` 但是一定要注意,一旦的函數確定要返回Promise對象,就一定要全部可能分支都要返回Promise對象,不然出了問題非常難定位。 舉個簡單的例子,i是奇數或偶數做不一樣的處理,一定要嚴謹。 promise/api/e.js ~~~ // 奇數和偶數 function hello(i){ if (i % 2 == 0) { return Promise.resolve(i) } else { return Promise.reject(i) } } hello(1).then(function(value){ console.log('Promise.reject 1 ' + value); }); hello(2).then(function(value){ console.log('Promise.resolve 1 ' + value); }); ~~~ 其實按照規范Promise.resolve和Promise.reject還有更多用法,其他的給出語法定義,了解一下即可,沒有特別需要說明的。 > Promise.resolve(value); Promise.resolve(promise); Promise.resolve(thenable); > > Promise.reject(reason); 2)核心方法Promise.prototype.then() 語法 > p.then(onFulfilled, onRejected); > > p.then(function(value) { // fulfillment }, function(reason) { // rejection }); 3)次核心方法Promise.prototype.catch() > p.catch(onRejected); > > p.catch(function(reason) { // rejection }); 4)工具方法 * Promise.all(iterable) * Promise.race(iterable) Promise.all 在接收到的所有的對象promise都變為 FulFilled 或者 Rejected 狀態之后才會繼續進行后面的處理, 與之相對的是 Promise.race 只要有一個promise對象進入 FulFilled 或者 Rejected 狀態的話,就會繼續進行后面的處理。 簡單點就說,all是所有都執行完成,再執行then,而race語義上相當于once,有個執行完成后就會執行then。一定要注意,它們是并發的,只是結果處理的點不一樣而已。 它們的使用方法是一樣,接收一個promise對象數組為參數。 all.js ~~~ 'use strict' let sleep = (time, info) => { return new Promise(function (resolve) { setTimeout(function () { console.log(info) resolve('this is ' + info) }, time) }) } let loser = sleep(1000, 'loser') let winner = sleep(4, 'winner') // main Promise.all([winner, loser]).then(value => { console.log("所有都完成后會執行then,它們是并行的哦: " + value) // => 'this is winner' }) ~~~ 執行結果 ~~~ $ node api/all.js winner loser 所有都完成后會執行then,它們是并行的哦: this is winner,this is loser ~~~ race.js ~~~ 'use strict' let sleep = (time, info) => { return new Promise(function (resolve) { setTimeout(function () { console.log(info) resolve('this is ' + info) }, time) }) } let loser = sleep(1000, 'loser') let winner = sleep(4, 'winner') // main Promise.race([winner, loser]).then(value => { console.log("只要有一個成功,就會執行then,和順序無關,只看執行速度: " + value) // => 'this is winner' }) ~~~ 執行結果 ~~~ $ node api/race.js winner 只要有一個成功,就會執行then,和順序無關,只看執行速度: this is winner loser ~~~ ## 參考閱讀 1. [Promises/A](http://wiki.commonjs.org/wiki/Promises/A) 2. [Promises/B](http://wiki.commonjs.org/wiki/Promises/B) 3. [Promises/D](http://wiki.commonjs.org/wiki/Promises/D) 4. [Promisejs](https://www.promisejs.org/) 5. [Promises/A+](https://promisesaplus.com/) 6. [As soon as possible](https://github.com/kriskowal/asap) 7. [A minimalist implementation of a javascript promise](https://gist.github.com/unscriptable/814052) 8. [Lightweight implementation of promises](http://stackoverflow.com/questions/12923533/lightweight-implementation-of-promises) 9. [How is a promise/defer library implemented?](http://stackoverflow.com/questions/17718673/how-is-a-promise-defer-library-implemented) 10. [Basic Javascript promise implementation attempt](http://stackoverflow.com/questions/23772801/basic-javascript-promise-implementation-attempt/23785244#23785244) 11. [You're Missing the Point of Promises](https://blog.domenic.me/youre-missing-the-point-of-promises/) 12. [Boom! Promises/A+ Was Born](http://www.slideshare.net/domenicdenicola/boom-promisesa-was-born) 13. [Futures and promises](http://en.wikipedia.org/wiki/Futures_and_promises) 14. [JavaScript Promises - There and back again](http://www.html5rocks.com/zh/tutorials/es6/promises/) 15. [Promise 迷你書](https://github.com/liubin/promises-book) 16. [https://blog.domenic.me/youre-missing-the-point-of-promises/](https://blog.domenic.me/youre-missing-the-point-of-promises/) 17. [https://strongloop.com/strongblog/promises-in-node-js-with-q-an-alternative-to-callbacks/](https://strongloop.com/strongblog/promises-in-node-js-with-q-an-alternative-to-callbacks/) 18. [https://github.com/kriskowal/q/wiki/General-Promise-Resources](https://github.com/kriskowal/q/wiki/General-Promise-Resources) 19. [https://www.w3.org/2001/tag/doc/promises-guide](https://www.w3.org/2001/tag/doc/promises-guide) 20. [https://github.com/bevacqua/promisees](https://github.com/bevacqua/promisees) 源碼?[https://github.com/calvinmetcalf/lie/blob/master/lib/index.js](https://github.com/calvinmetcalf/lie/blob/master/lib/index.js)
                  <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>

                              哎呀哎呀视频在线观看