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

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## Promise的歷史 在Promise出現之前,如果大家需要實現異步操作,通用的做法是事件加上回調函數,如果我們有多個異步操作需要嵌套執行的話,那么代碼將變得非常難于閱讀。讓我們來看一個具體的代碼例子。在下面的例子中,我們首先通過Http request調用一個web service,然后將從web service收到的數據寫入一個本地文件。從任務的角度來看,這是一個非常簡單的任務,但是當你第一次看到這個代碼的時候,一定覺得頭很暈,因為在這段代碼中 * 對web service進行調用的代碼和寫文件的代碼混雜在一起(寫文件的代碼嵌套在`end`事件的回調函數中),造成代碼模塊不清晰,閱讀和理解起來比較費勁。 * 對錯誤的處理分散在代碼的各個地方,而且錯誤處理的實現方式都不一樣。對web service進行調用的代碼,通過監聽`error`事件來處理錯誤,并且將錯誤輸出到控制套;而寫文件的代碼,是通過回調函數來處理錯誤,并將錯誤通過`throw`語句拋出。 ```javascript var http = require("http"); var fs = require("fs"); var querystring = require("querystring"); var postData = querystring.stringify({ 'msg' : 'Hello World!' }); var options = { hostname: '127.0.0.1', port: 8080, path: '/upload', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length } }; var req = http.request(options, (res) => { console.log(`STATUS: ${res.statusCode}`); console.log(`HEADERS: ${JSON.stringify(res.headers)}`); res.setEncoding('utf8'); var dataReceived = "" res.on('data', (chunk) => { dataReceived = dataReceived + chunk.toString(); console.log(`BODY: ${chunk}`); }); res.on('end', () => { console.log('No more data in response.') //now we try to write the message to a file fs.writeFile("temp.txt", dataReceived, function(err){ if (err){ throw err; } console.log("Write file temp.txt succ"); }); }) }); req.on('error', (e) => { console.log(`problem with request: ${e.message}`); }); // write data to request body req.write(postData); req.end(); ``` 接下來,讓我們使用Promise重寫上面的代碼。在重寫的代碼中,我們可以看到: * 對web service進行調用的代碼和寫文件的代碼完全分離開了,代碼結構變得非常清晰。在閱讀代碼的過程中,不會再被不相關的代碼所干擾。 * Promise對象對外提供了統一的回調函數接口(resolve和reject回調函數 ),在重寫的代碼中,我們可以很容易的把對web service的請求分裝到一個模塊中,從而對外隱藏Http Request的所有細節。 * 通過Promise對象的封裝,對錯誤代碼的處理被統一了,都是通過對`reject`函數調用來說明異步操作過程中有錯誤發生,而且錯誤被集中到`.catch`代碼段進行了處理(錯誤都被輸出到了控制臺)。 * 通過Promise的封裝,異步操作的代碼變得和同步操作代碼很像,更方便其他人理解代碼的處理邏輯。 ```javascript 'use strict'; var http = require("http"); var fs = require("fs"); var querystring = require("querystring"); var postData = querystring.stringify({ 'msg' : 'Hello World!' }); var options = { hostname: '127.0.0.1', port: 8080, path: '/upload', method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length } }; var pHttpRequest = new Promise(function(resolve, reject){ let req = http.request(options, (res) => { console.log(`STATUS: ${res.statusCode}`); console.log(`HEADERS: ${JSON.stringify(res.headers)}`); res.setEncoding('utf8'); let dataReceived = "" res.on('data', (chunk) => { dataReceived = dataReceived + chunk.toString(); }); res.on('end', () => { resolve(dataReceived); }) }); req.on('error', function(e){ reject(e); }); req.write(postData); req.end(); }) pHttpRequest.then( //http request promise成功時候的處理 //在http request promise成功的時候,開始處理寫文件操作 function(dataReceived){ return new Promise(function(resolve, reject){ fs.writeFile("temp.txt", dataReceived, function(e){ if (e) reject(e); else resolve("Write file succ"); }); }) } ).then( //writeFile promise成功時候的處理 function(msg){ console.log(msg); } ).catch( //全局錯誤處理 function(err){ console.log("some error happen(" + err + ")"); } ) ``` 正式基于Promise對象有上面所說的這些優點,ES6正式將Promise對象編程了系統的一個內置對象,大家再也不用通過第三方庫開始用Promise對象了。 ## Promise對象的特性 * Promise對象一旦創建,就開始執行了,你沒有辦法取消Promise對象的執行。 * Promise對象的狀態只由異步操作的結果決定,沒有任何其他的操作可以改變Promise對象的狀態如果異步操作執行成功,Promise對象將進入Resolved狀態,同時resolve函數將被調用;如果異步操作執行失敗,Promise對象將進入Rejected狀態,同時reject函數將被調用。 * Promise對象一旦進入Resolved或者Rejected狀態,狀態將不可能再發生變化,在Promise對象被銷毀之前,將一直保持Resolved或者Rejected狀態。 * 因為Promise對象的實現方法,在異步操作過程中出現的異常是不會被拋出的,因此需要在Promise對象內部進行處理(通過提供`.catch`代碼段來實現)。 下圖表示了一個Promise對象的整個生命周期。 ![](promise_lifecycle.png) ## Promise對象的使用 創建Promise對象 -------------------------------------------------------------------------------- 在ES6中,你可以通過```new Promise(function(resolve, reject){ })```來創建Promise對象,下面是一個具體的代碼。 ```javascript 'use strict'; var fs = require("fs"); var promiseObj = new Promise(function(resolve, reject){ //put some code to call fs.readFile("temp.txt", (err, data) => { if (err){ reject(err); }else{ resolved(data); } }); }); ``` 關聯resolve function和reject function -------------------------------------------------------------------------------- 在上面的例子中,如果你執行這個代碼,你會發現沒有任何的效果(沒有輸出),那是因為你沒有給這個創建的Promise對象關聯相應的resolve和reject函數。下面是一個進一步的例子,這個例子將給Promise對象綁定resolve和reject函數,你就可以看到效果了。在我的測試環境中,因為我們有名為"temp.txt"的文件存在,所以輸出了```file read fail```。 ```javascript 'use strict'; var fs = require("fs"); var promiseObj = new Promise(function(resolve, reject){ //put some code to call fs.readFile("temp.txt", (err, data) => { if (err){ reject(err); }else{ resolved(data); } }); }); promiseObj.then(function(data){ console.log("file read succ"); }, function(err){ console.log("file read fail"); }) ``` 在通常情況下,reject狀態的函數我們一般不在then中設置,而是在catch中設置,這樣代碼看起來更像是傳統意義上的同步代碼(和try...catch比較)。因此上面的例子可以重新寫成 ```javascript 'use strict'; var fs = require("fs"); var promiseObj = new Promise(function(resolve, reject){ //put some code to call fs.readFile("temp.txt", (err, data) => { if (err){ reject(err); }else{ resolved(data); } }); }); promiseObj.then(function(data){ console.log("file read succ"); }).catch(function(err){ console.log("file read fail"); }); ``` 級聯多個Promise對象 -------------------------------------------------------------------------------- Promise對象的resolve函數的參數可以是另外一個Promise對象,這樣就可以將2個Promise對象級聯起來。下面是一個簡單的例子 ```javascript 'use strict'; var p1 = new Promise(function(resolve, reject){ setTimeout(() => reject(new Error("something test"), 3000)); }); var p2 = new Promise(function(resolve, reject){ setTimeout(() => resolve(p1), 1000); }); p2.then(function(data){ console.log("p2 succ"); }).catch(function(err){ console.log("p2 fail"); }); ``` ## Promise的特殊函數 Promise.all() -------------------------------------------------------------------------------- 將多個Promise包裝成一個全新的Promise Object,如果所有的Promise被Resolved,那么新的Promise將被Resolve;否則新的Promise將被Reject。 Promise.race() -------------------------------------------------------------------------------- 和.all一樣,.race將把多個Promise包裝成一個新的Promise Object,不同的地方是。這些Promise之中任何一個Resolve或者Reject了,新的Promise就被Resolve或者Reject了。 Promise.resolve() -------------------------------------------------------------------------------- 將傳入的對象封裝成一個Promise對象返回。resolve方法根據以下的規則返回Promise對象。 * 如果輸入的參數本身是一個Promise對象,那么resolve方法直接返回這個對象; * 如果輸入的對象本身有then方法(必須是一個可以接受2個function的方法),那么resolve將這個對象轉換成Promise對象,并理解調用then方法;下面是一個例子 ```javascript //for this example, you will see following output // then function in thenobject // Promise object resolve function is called Then function is called var thenobject = { then: function(resolve, reject){ console.log("then function in thenobject"); resolve("Then function is called"); } }; var pObj = Promise.resolve(thenobject); pObj.then(function(data){ console.log("Promise object resolve function is called " + data); }); ``` * 如果傳入的參數就是一個普通對象,那么返回的Promise對象直接處于resolved狀態,并且輸入的參數將作為resolved狀態下調用的函數的參數。下面是一個具體的例子。 ```javascript //for this example, you will see following output // Promise object resolve function is called Hello World! var pObj = Promise.resolve("Hello World!"); pObj.then(function(data){ console.log("Promise object resolve function is called " + data); }); ``` *如果沒有輸入參數,那么返回的Promise對象直接處于resolved狀態,并且resolved狀態下調用的函數沒有輸入參數。 done() method -------------------------------------------------------------------------------- 通過在Promise的調用鏈最后使用這個方法,可以保證catch到任何的錯誤。 finally() method -------------------------------------------------------------------------------- 如果你需要在Promise結束的時候(不管resolve還是reject結束),都有一個函數被調用,那么就需要使用這個方法。這個方法接受一個回調函數作為輸入。當Promise結束的時候,這個回調函數將被調用。
                  <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>

                              哎呀哎呀视频在线观看