<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      深入理解 JavaScript 異步系列(3)—— ES6 中的 Promise

      第一部分,Promise 加入 ES6 標(biāo)準(zhǔn)

      原文地址 http://www.rzrgm.cn/wangfupeng1988/p/6515855.html 未經(jīng)作者允許不得轉(zhuǎn)載!

      從 jquery v1.5 發(fā)布經(jīng)過若干時間之后,Promise 終于出現(xiàn)在了 ES6 的標(biāo)準(zhǔn)中,而當(dāng)下 ES6 也正在被大規(guī)模使用。

      本節(jié)展示的代碼參考這里

      本節(jié)內(nèi)容概述

      • 寫一段傳統(tǒng)的異步操作
      • Promise進(jìn)行封裝

      寫一段傳統(tǒng)的異步操作

      還是拿之前講 jquery deferred對象時的那段setTimeout程序

      var wait = function () {
          var task = function () {
              console.log('執(zhí)行完成')
          }
          setTimeout(task, 2000)
      }
      wait()

      之前我們使用 jquery 封裝的,接下來將使用 ES6 的Promise進(jìn)行封裝,大家注意看有何不同。

      Promise進(jìn)行封裝

      const wait =  function () {
          // 定義一個 promise 對象
          const promise = new Promise((resolve, reject) => {
              // 將之前的異步操作,包括到這個 new Promise 函數(shù)之內(nèi)
              const task = function () {
                  console.log('執(zhí)行完成')
                  resolve()  // callback 中去執(zhí)行 resolve 或者 reject
              }
              setTimeout(task, 2000)
          })
          // 返回 promise 對象
          return promise
      }

      注意看看程序中的注釋,那都是重點部分。從整體看來,感覺這次比用 jquery 那次簡單一些,邏輯上也更加清晰一些。

      • 將之前的異步操作那幾行程序,用new Promise((resolve,reject) => {.....})包裝起來,最后return即可
      • 異步操作的內(nèi)部,在callback中執(zhí)行resolve()(表明成功了,失敗的話執(zhí)行reject

      接著上面的程序繼續(xù)往下寫。wait()返回的肯定是一個promise對象,而promise對象有then屬性。

      const w = wait()
      w.then(() => {
          console.log('ok 1')
      }, () => {
          console.log('err 1')
      }).then(() => {
          console.log('ok 2')
      }, () => {
          console.log('err 2')
      })

      then還是和之前一樣,接收兩個參數(shù)(函數(shù)),第一個在成功時(觸發(fā)resolve)執(zhí)行,第二個在失敗時(觸發(fā)reject)時執(zhí)行。而且,then還可以進(jìn)行鏈?zhǔn)讲僮鳌?/p>

      以上就是 ES6 的Promise的基本使用演示。看完你可能會覺得,這跟之前講述 jquery 的不差不多嗎 ———— 對了,這就是我要在之前先講 jquery 的原因,讓你感覺一篇一篇看起來如絲般順滑!

      接下來,將詳細(xì)說一下 ES6 Promise 的一些比較常見的用法,敬請期待吧!

       

      第二部分,Promise 在 ES6 中的具體應(yīng)用

      上一節(jié)對 ES6 的 Promise 有了一個最簡單的介紹,這一節(jié)詳細(xì)說一下 Promise 那些最常見的功能

      本節(jié)展示的代碼參考這里

      本節(jié)課程概述

      • 準(zhǔn)備工作
      • 參數(shù)傳遞
      • 異常捕獲
      • 串聯(lián)多個異步操作
      • Promise.allPromise.race的應(yīng)用
      • Promise.resolve的應(yīng)用
      • 其他

      準(zhǔn)備工作

      因為以下所有的代碼都會用到Promise,因此干脆在所有介紹之前,先封裝一個Promise,封裝一次,為下面多次應(yīng)用。

      const fs = require('fs')
      const path = require('path')  // 后面獲取文件路徑時候會用到
      const readFilePromise = function (fileName) {
          return new Promise((resolve, reject) => {
              fs.readFile(fileName, (err, data) => {
                  if (err) {
                      reject(err)  // 注意,這里執(zhí)行 reject 是傳遞了參數(shù),后面會有地方接收到這個參數(shù)
                  } else {
                      resolve(data.toString())  // 注意,這里執(zhí)行 resolve 時傳遞了參數(shù),后面會有地方接收到這個參數(shù)
                  }
              })
          })
      }

      以上代碼一個一段 nodejs 代碼,將讀取文件的函數(shù)fs.readFile封裝為一個Promise。經(jīng)過上一節(jié)的學(xué)習(xí),我想大家肯定都能看明白代碼的含義,要是看不明白,你就需要回爐重造了!

      參數(shù)傳遞

      我們要使用上面封裝的readFilePromise讀取一個 json 文件../data/data2.json,這個文件內(nèi)容非常簡單:{"a":100, "b":200}

      先將文件內(nèi)容打印出來,代碼如下。大家需要注意,readFilePromise函數(shù)中,執(zhí)行resolve(data.toString())傳遞的參數(shù)內(nèi)容,會被下面代碼中的data參數(shù)所接收到。

      const fullFileName = path.resolve(__dirname, '../data/data2.json')
      const result = readFilePromise(fullFileName)
      result.then(data => {
          console.log(data)
      })

      再加一個需求,在打印出文件內(nèi)容之后,我還想看看a屬性的值,代碼如下。之前我們已經(jīng)知道then可以執(zhí)行鏈?zhǔn)讲僮鳎绻?code>then有多步驟的操作,那么前面步驟return的值會被當(dāng)做參數(shù)傳遞給后面步驟的函數(shù),如下面代碼中的a就接收到了return JSON.parse(data).a的值

      const fullFileName = path.resolve(__dirname, '../data/data2.json')
      const result = readFilePromise(fullFileName)
      result.then(data => {
          // 第一步操作
          console.log(data)
          return JSON.parse(data).a  // 這里將 a 屬性的值 return
      }).then(a => {
          // 第二步操作
          console.log(a)  // 這里可以獲取上一步 return 過來的值
      })

      總結(jié)一下,這一段內(nèi)容提到的“參數(shù)傳遞”其實有兩個方面:

      • 執(zhí)行resolve傳遞的值,會被第一個then處理時接收到
      • 如果then有鏈?zhǔn)讲僮鳎懊娌襟E返回的值,會被后面的步驟獲取到

      異常捕獲

      我們知道then會接收兩個參數(shù)(函數(shù)),第一個參數(shù)會在執(zhí)行resolve之后觸發(fā)(還能傳遞參數(shù)),第二個參數(shù)會在執(zhí)行reject之后觸發(fā)(其實也可以傳遞參數(shù),和resolve傳遞參數(shù)一樣),但是上面的例子中,我們沒有用到then的第二個參數(shù)。這是為何呢 ———— 因為不建議這么用。

      對于Promise中的異常處理,我們建議用catch方法,而不是then的第二個參數(shù)。請看下面的代碼,以及注釋。

      const fullFileName = path.resolve(__dirname, '../data/data2.json')
      const result = readFilePromise(fullFileName)
      result.then(data => {
          console.log(data)
          return JSON.parse(data).a
      }).then(a => {
          console.log(a)
      }).catch(err => {
          console.log(err.stack)  // 這里的 catch 就能捕獲 readFilePromise 中觸發(fā)的 reject ,而且能接收 reject 傳遞的參數(shù)
      })

      在若干個then串聯(lián)之后,我們一般會在最后跟一個.catch來捕獲異常,而且執(zhí)行reject時傳遞的參數(shù)也會在catch中獲取到。這樣做的好處是:

      • 讓程序看起來更加簡潔,是一個串聯(lián)的關(guān)系,沒有分支(如果用then的兩個參數(shù),就會出現(xiàn)分支,影響閱讀)
      • 看起來更像是try - catch的樣子,更易理解

      串聯(lián)多個異步操作

      如果現(xiàn)在有一個需求:先讀取data2.json的內(nèi)容,當(dāng)成功之后,再去讀取data1.json。這樣的需求,如果用傳統(tǒng)的callback去實現(xiàn),會變得很麻煩。而且,現(xiàn)在只是兩個文件,如果是十幾個文件這樣做,寫出來的代碼就沒法看了(臭名昭著的callback-hell)。但是用剛剛學(xué)到的Promise就可以輕松勝任這項工作

      const fullFileName2 = path.resolve(__dirname, '../data/data2.json')
      const result2 = readFilePromise(fullFileName2)
      const fullFileName1 = path.resolve(__dirname, '../data/data1.json')
      const result1 = readFilePromise(fullFileName1)
      
      result2.then(data => {
          console.log('data2.json', data)
          return result1  // 此處只需返回讀取 data1.json 的 Promise 即可
      }).then(data => {
          console.log('data1.json', data) // data 即可接收到 data1.json 的內(nèi)容
      })

      上文“參數(shù)傳遞”提到過,如果then有鏈?zhǔn)讲僮鳎懊娌襟E返回的值,會被后面的步驟獲取到。但是,如果前面步驟返回值是一個Promise的話,情況就不一樣了 ———— 如果前面返回的是Promise對象,后面的then將會被當(dāng)做這個返回的Promise的第一個then來對待 ———— 如果你這句話看不懂,你需要將“參數(shù)傳遞”的示例代碼和這里的示例代碼聯(lián)合起來對比著看,然后體會這句話的意思。

      Promise.allPromise.race的應(yīng)用

      我還得繼續(xù)提出更加奇葩的需求,以演示Promise的各個常用功能。如下需求:

      讀取兩個文件data1.jsondata2.json,現(xiàn)在我需要一起讀取這兩個文件,等待它們?nèi)慷急蛔x取完,再做下一步的操作。此時需要用到Promise.all

      // Promise.all 接收一個包含多個 promise 對象的數(shù)組
      Promise.all([result1, result2]).then(datas => {
          // 接收到的 datas 是一個數(shù)組,依次包含了多個 promise 返回的內(nèi)容
          console.log(datas[0])
          console.log(datas[1])
      })

      讀取兩個文件data1.jsondata2.json,現(xiàn)在我需要一起讀取這兩個文件,但是只要有一個已經(jīng)讀取了,就可以進(jìn)行下一步的操作。此時需要用到Promise.race

      // Promise.race 接收一個包含多個 promise 對象的數(shù)組
      Promise.race([result1, result2]).then(data => {
          // data 即最先執(zhí)行完成的 promise 的返回值
          console.log(data)
      })

      Promise.resolve的應(yīng)用

      從 jquery 引出,到此即將介紹完 ES6 的Promise,現(xiàn)在我們再回歸到 jquery 。

      大家都是到 jquery v1.5 之后$.ajax()返回的是一個deferred對象,而這個deferred對象和我們現(xiàn)在正在學(xué)習(xí)的Promise對象已經(jīng)很接近了,但是還不一樣。那么 ———— deferred對象能否轉(zhuǎn)換成 ES6 的Promise對象來使用??

      答案是能!需要使用Promise.resolve來實現(xiàn)這一功能,請看以下代碼:

      // 在瀏覽器環(huán)境下運行,而非 node 環(huán)境
      cosnt jsPromise = Promise.resolve($.ajax('/whatever.json'))
      jsPromise.then(data => {
          // ...
      })

      注意:這里的Promise.resolve和文章最初readFilePromise函數(shù)內(nèi)部的resolve函數(shù)可千萬不要混了,完全是兩碼事兒。JS 基礎(chǔ)好的同學(xué)一看就明白,而這里看不明白的同學(xué),要特別注意。

      實際上,并不是Promise.resolve對 jquery 的deferred對象做了特殊處理,而是Promise.resolve能夠?qū)?code>thenable對象轉(zhuǎn)換為Promise對象。什么是thenable對象?———— 看個例子

      // 定義一個 thenable 對象
      const thenable = {
          // 所謂 thenable 對象,就是具有 then 屬性,而且屬性值是如下格式函數(shù)的對象
          then: (resolve, reject) => {
              resolve(200)
          }
      }
      
      // thenable 對象可以轉(zhuǎn)換為 Promise 對象
      const promise = Promise.resolve(thenable)
      promise.then(data => {
          // ...
      })

      上面的代碼就將一個thenalbe對象轉(zhuǎn)換為一個Promise對象,只不過這里沒有異步操作,所有的都會同步執(zhí)行,但是不會報錯的。

      其實,在我們的日常開發(fā)中,這種將thenable轉(zhuǎn)換為Promise的需求并不多。真正需要的是,將一些異步操作函數(shù)(如fs.readFile)轉(zhuǎn)換為Promise(就像文章一開始readFilePromise做的那樣)。這塊,我們后面會在介紹Q.js庫時,告訴大家一個簡單的方法。

      其他

      以上都是一些日常開發(fā)中非常常用的功能,其他詳細(xì)的介紹,請參考阮一峰老師的 ES6 教程 Promise 篇

      最后,本節(jié)我們只是介紹了Promise的一些應(yīng)用,通俗易懂拿來就用的東西,但是沒有提升到理論和標(biāo)準(zhǔn)的高度。有人可能會不屑 ———— 我會用就行了,要那么空談的理論干嘛?———— 你只會使用卻上升不到理論高度,永遠(yuǎn)都是個搬磚的,搬一塊磚掙一毛錢,不搬就不掙錢! 在我看來,所有的知識應(yīng)該都需要上升到理論高度,將實際應(yīng)用和標(biāo)準(zhǔn)對接,知道真正的出處,才能走的長遠(yuǎn)。

      下一節(jié)我們介紹 Promise/A+ 規(guī)范

       

      第三部分,對標(biāo)一下 Promise/A+ 規(guī)范

      Promise/A 是由 CommonJS 組織制定的異步模式編程規(guī)范,后來又經(jīng)過一些升級,就是當(dāng)前的 Promise/A+ 規(guī)范。上一節(jié)講述的Promise的一些功能實現(xiàn),就是根據(jù)這個規(guī)范來的。

      本節(jié)內(nèi)容概述

      • 介紹規(guī)范的核心內(nèi)容
      • 狀態(tài)變化
      • then方法
      • 接下來...

      介紹規(guī)范的核心內(nèi)容

      網(wǎng)上有很多介紹 Promise/A+ 規(guī)范的文章,大家可以搜索來看,但是它的核心要點有以下幾個,我也是從看了之后自己總結(jié)的

      關(guān)于狀態(tài)

      • promise 可能有三種狀態(tài):等待(pending)、已完成(fulfilled)、已拒絕(rejected)
      • promise 的狀態(tài)只可能從“等待”轉(zhuǎn)到“完成”態(tài)或者“拒絕”態(tài),不能逆向轉(zhuǎn)換,同時“完成”態(tài)和“拒絕”態(tài)不能相互轉(zhuǎn)換

      關(guān)于then方法

      • promise 必須實現(xiàn)then方法,而且then必須返回一個 promise ,同一個 promise 的then可以調(diào)用多次(鏈?zhǔn)剑⑶一卣{(diào)的執(zhí)行順序跟它們被定義時的順序一致
      • then方法接受兩個參數(shù),第一個參數(shù)是成功時的回調(diào),在 promise 由“等待”態(tài)轉(zhuǎn)換到“完成”態(tài)時調(diào)用,另一個是失敗時的回調(diào),在 promise 由“等待”態(tài)轉(zhuǎn)換到“拒絕”態(tài)時調(diào)用

      下面挨個介紹這些規(guī)范在上一節(jié)代碼中的實現(xiàn),所謂理論與實踐相結(jié)合。在閱讀以下內(nèi)容時,你要時刻準(zhǔn)備參考上一節(jié)的代碼。

      狀態(tài)變化

      promise 可能有三種狀態(tài):等待(pending)、已完成(fulfilled)、已拒絕(rejected)

      拿到上一節(jié)的readFilePromise函數(shù),然后執(zhí)行const result = readFilePromise(someFileName)會得到一個Promise對象。

      • 剛剛創(chuàng)建時,就是 等待(pending)狀態(tài)
      • 如果讀取文件成功了,readFilePromise函數(shù)內(nèi)部的callback中會自定調(diào)用resolve(),這樣就變?yōu)?已完成(fulfilled)狀態(tài)
      • 如果很不幸讀取文件失敗了(例如文件名寫錯了,找不到文件),readFilePromise函數(shù)內(nèi)部的callback中會自定調(diào)用reject(),這樣就變?yōu)?已拒絕(rejeced)狀態(tài)

      promise 的狀態(tài)只可能從“等待”轉(zhuǎn)到“完成”態(tài)或者“拒絕”態(tài),不能逆向轉(zhuǎn)換,同時“完成”態(tài)和“拒絕”態(tài)不能相互轉(zhuǎn)換

      這個規(guī)則還是可以參考讀取文件的這個例子。從一開始準(zhǔn)備讀取,到最后無論是讀取成功或是讀取失敗,都是不可逆的。另外,讀取成功和讀取失敗之間,也是不能互換的。這個邏輯沒有任何問題,很好理解。

      then方法

      promise 必須實現(xiàn)then方法,而且then必須返回一個 promise ,同一個 promise 的then可以調(diào)用多次(鏈?zhǔn)剑⑶一卣{(diào)的執(zhí)行順序跟它們被定義時的順序一致

      • promise對象必須實現(xiàn)then方法這個無需解釋,沒有then那就不叫promise
      • “而且then必須返回一個promise,同一個 promise 的then可以調(diào)用多次(鏈?zhǔn)剑?———— 這兩句話說明了一個意思 ———— then肯定要再返回一個promise,要不然then后面怎么能再鏈?zhǔn)降母粋€then呢?

      then方法接受兩個參數(shù),第一個參數(shù)是成功時的回調(diào),在 promise 由“等待”態(tài)轉(zhuǎn)換到“完成”態(tài)時調(diào)用,另一個是失敗時的回調(diào),在 promise 由“等待”態(tài)轉(zhuǎn)換到“拒絕”態(tài)時調(diào)用

      這句話比較好理解了,我們從一開始就在 demo 中演示。

      接下來...

      Promise的應(yīng)用、規(guī)范都介紹完了,看起來挺牛的,也解決了異步操作中使用callback帶來的很多問題。但是Promise本質(zhì)上到底是一種什么樣的存在,它是真的把callback棄而不用了嗎,還是兩者有什么合作關(guān)系?它到底是真的神通廣大,還是使用了障眼法?

      這些問題,大家學(xué)完Promise之后應(yīng)該去思考,不能光學(xué)會怎么用就停止了。下一節(jié)我們一起來探討~

       

      第四部分,Promise 真的取代 callback 了嗎

      Promise 雖然改變了 JS 工程師對于異步操作的寫法,但是卻改變不了 JS 單線程、異步的執(zhí)行模式。

      本節(jié)概述

      • JS 異步的本質(zhì)
      • Promise 只是表面的寫法上的改變
      • Promise 中不能缺少 callback
      • 接下來...

      JS 異步的本質(zhì)

      從最初的 ES3、4 到 ES5 再到現(xiàn)在的 ES6 和即將到來的 ES7,語法標(biāo)準(zhǔn)上更新很多,但是 JS 這種單線程、異步的本質(zhì)是沒有改變的。nodejs 中讀取文件的代碼一直都可以這樣寫

      fs.readFile('some.json', (err, data) => {
      })

      既然異步這個本質(zhì)不能改變,伴隨異步在一起的永遠(yuǎn)都會有callback,因為沒有callback就無法實現(xiàn)異步。因此callback永遠(yuǎn)存在。

      Promise 只是表面的寫法上的改變

      JS 工程師不會討厭 JS 異步的本質(zhì),但是很討厭 JS 異步操作中callback的書寫方式,特別是遇到萬惡的callback-hell(嵌套callback)時。

      計算機(jī)的抽象思維和人的具象思維是完全不一樣的,人永遠(yuǎn)喜歡看起來更加符合邏輯、更加易于閱讀的程序,因此現(xiàn)在特別強(qiáng)調(diào)代碼可讀性。而Promise就是一種代碼可讀性的變化。大家感受一下這兩種不同(這其中還包括異常處理,加上異常處理會更加復(fù)雜)

      第一種,傳統(tǒng)的callback方式

      fs.readFile('some1.json', (err, data) => {
          fs.readFile('some2.json', (err, data) => {
              fs.readFile('some3.json', (err, data) => {
                  fs.readFile('some4.json', (err, data) => {
      
                  })
              })
          })
      })

      第二種,Promise方式

      readFilePromise('some1.json').then(data => {
          return readFilePromise('some2.json')
      }).then(data => {
          return readFilePromise('some3.json')
      }).then(data => {
          return readFilePromise('some4.json')
      })

      這兩種方式對于代碼可讀性的對比,非常明顯。但是最后再次強(qiáng)調(diào),Promise只是對于異步操作代碼可讀性的一種變化,它并沒有改變 JS 異步執(zhí)行的本質(zhì),也沒有改變 JS 中存在callback的現(xiàn)象。

      Promise 中不能缺少 callback

      上文已經(jīng)基本給出了上一節(jié)提問的答案,但是這里還需要再加一個補(bǔ)充:Promise不僅僅是沒有取代callback或者棄而不用,反而Promise中要使用到callback。因為,JS 異步執(zhí)行的本質(zhì),必須有callback存在,否則無法實現(xiàn)。

      再次粘貼處之前章節(jié)的封裝好的一個Promise函數(shù)(進(jìn)行了一點點簡化)

      const readFilePromise = function (fileName) {
          return new Promise((resolve, reject) => {
              fs.readFile(fileName, (err, data) => {
                  resolve(data.toString())
              })
          })
      }

      上面的代碼中,promise對象的狀態(tài)要從pending變化為fulfilled,就需要去執(zhí)行resolve()函數(shù)。那么是從哪里執(zhí)行的 ———— 還得從callback中執(zhí)行resolve函數(shù) ———— 這就是Promise也需要callback的最直接體現(xiàn)。

      接下來...

      一塊技術(shù)“火”的程度和第三方開源軟件的數(shù)量、質(zhì)量以及使用情況有很大的正比關(guān)系。例如為了簡化 DOM 操作,jquery 風(fēng)靡全世界。Promise 用的比較多,第三方庫當(dāng)然就必不可少,它們極大程度的簡化了 Promise 的代碼。

      接下來我們一起看看Q.js這個庫的使用,學(xué)會了它,將極大程度提高你寫 Promise 的效率。

       

      第五部分,使用 Q.js 庫

      如果實際項目中使用Promise,還是強(qiáng)烈建議使用比較靠譜的第三方插件,會極大增加你的開發(fā)效率。除了將要介紹的Q.js,還有bluebird也推薦使用,去 github 自行搜索吧。

      另外,使用第三方庫不僅僅是提高效率,它還讓你在瀏覽器端(不支持Promise的環(huán)境中)使用promise

      本節(jié)展示的代碼參考這里

      本節(jié)內(nèi)容概述

      • 下載和安裝
      • 使用Q.nfcallQ.nfapply
      • 使用Q.defer
      • 使用Q.denodeify
      • 使用Q.allQ.any
      • 使用Q.delay
      • 其他

      下載和安裝

      可以直接去它的 github 地址 (近 1.3W 的 star 數(shù)量說明其用戶群很大)查看文檔。

      如果項目使用 CommonJS 規(guī)范直接 npm i q --save,如果是網(wǎng)頁外鏈可尋找可用的 cdn 地址,或者干脆下載到本地。

      以下我將要演示的代碼,都是使用 CommonJS 規(guī)范的,因此我要演示代碼之前加上引用,以后的代碼演示就不重復(fù)加了。

      const Q = require('q')

      使用Q.nfcallQ.nfapply

      要使用這兩個函數(shù),你得首先了解 JS 的callapply,如果不了解,先去看看。熟悉了這兩個函數(shù)之后,再回來看。

      Q.nfcall就是使用call的語法來返回一個promise對象,例如

      const fullFileName = path.resolve(__dirname, '../data/data1.json')
      const result = Q.nfcall(fs.readFile, fullFileName, 'utf-8')  // 使用 Q.nfcall 返回一個 promise
      result.then(data => {
          console.log(data)
      }).catch(err => {
          console.log(err.stack)
      })

      Q.nfapply就是使用apply的語法返回一個promise對象,例如

      const fullFileName = path.resolve(__dirname, '../data/data1.json')
      const result = Q.nfapply(fs.readFile, [fullFileName, 'utf-8'])  // 使用 Q.nfapply 返回一個 promise
      result.then(data => {
          console.log(data)
      }).catch(err => {
          console.log(err.stack)
      })

      怎么樣,體驗了一把,是不是比直接自己寫Promise簡單多了?

      使用Q.defer

      Q.defer算是一個比較偏底層一點的 API ,用于自己定義一個promise生成器,如果你需要在瀏覽器端編寫,而且瀏覽器不支持Promise,這個就有用處了。

      function readFile(fileName) {
          const defer = Q.defer()
          fs.readFile(fileName, (err, data) => {
              if (err) {
                  defer.reject(err)
              } else {
                  defer.resolve(data.toString())
              }
          })
          return defer.promise
      }
      readFile('data1.json')
          .then(data => {
              console.log(data)
          })
          .catch(err => {
              console.log(err.stack)
          })

      使用Q.denodeify

      我們在很早之前的一節(jié)中自己封裝了一個fs.readFilepromise生成器,這里再次回顧一下

      const readFilePromise = function (fileName) {
          return new Promise((resolve, reject) => {
              fs.readFile(fileName, (err, data) => {
                  if (err) {
                      reject(err)
                  } else {
                      resolve(data.toString())
                  }
              })
          })
      }

      雖然看著不麻煩,但是還是需要很多行代碼來實現(xiàn),如果使用Q.denodeify,一行代碼就搞定了!

      const readFilePromise = Q.denodeify(fs.readFile)

      Q.denodeif就是一鍵將fs.readFile這種有回調(diào)函數(shù)作為參數(shù)的異步操作封裝成一個promise生成器,非常方便!

      使用Q.allQ.any

      這兩個其實就是對應(yīng)了之前講過的Promise.allPromise.race,而且應(yīng)用起來一模一樣,不多贅述。

      const r1 = Q.nfcall(fs.readFile, 'data1.json', 'utf-8')
      const r2 = Q.nfcall(fs.readFile, 'data2.json', 'utf-8')
      Q.all([r1, r2]).then(arr => {
          console.log(arr)
      }).catch(err => {
          console.log(err)
      })

      使用Q.delay

      Q.delay,顧名思義,就是延遲的意思。例如,讀取一個文件成功之后,再過五秒鐘之后,再去做xxxx。這個如果是自己寫的話,也挺費勁的,但是Q.delay就直接給我們分裝好了。

      const result = Q.nfcall(fs.readFile, 'data1.json', 'utf-8')
      result.delay(5000).then(data => {
          // 得到結(jié)果
          console.log(data.toString())
      }).catch(err => {
          // 捕獲錯誤
          console.log(err.stack)
      })

      其他

      以上就是Q.js一些最常用的操作,其他的一些非常用技巧,大家可以去搜索或者去官網(wǎng)查看文檔。

      至此,ES6 Promise的所有內(nèi)容就已經(jīng)講完了。但是異步操作的優(yōu)化到這里沒有結(jié)束,更加精彩的內(nèi)容還在后面 ———— Generator

      求打賞

      如果你看完了,感覺還不錯,歡迎給我打賞 ———— 以激勵我更多輸出優(yōu)質(zhì)內(nèi)容

      最后,github地址是 https://github.com/wangfupeng1988/js-async-tutorial 歡迎 star 和 pr

      -----------------

      學(xué)習(xí)作者教程:《前端JS高級面試》《前端JS基礎(chǔ)面試題》《React.js模擬大眾點評webapp》《zepto設(shè)計與源碼分析》《json2.js源碼解讀

      posted @ 2017-03-09 09:23  王福朋  閱讀(14433)  評論(7)    收藏  舉報
      主站蜘蛛池模板: 国产中年熟女高潮大集合| 营口市| 一亚洲一区二区中文字幕| 国产小受被做到哭咬床单GV| 永登县| 国产成人午夜一区二区三区| 天堂mv在线mv免费mv香蕉| 高清偷拍一区二区三区| 高清中文字幕国产精品| 无码免费大香伊蕉在人线国产 | 亚洲人成网网址在线看| 毛片大全真人在线| 国产内射性高湖| 2021国产精品视频网站| 91精品91久久久久久| 亚洲精品成人综合色在线| 91福利视频一区二区| 伊金霍洛旗| 久久99九九精品久久久久蜜桃| AV毛片无码中文字幕不卡| 镇赉县| 国产三级a三级三级| 久久综合久色欧美综合狠狠| 99精品热在线在线观看视| 变态另类视频一区二区三区| 成在线人视频免费视频| аⅴ天堂国产最新版在线中文 | 亚洲精品麻豆一二三区| 西西人体44www大胆无码| 成年女人黄小视频| 国产乱码精品一区二三区| 未满十八18禁止免费无码网站| 亚洲午夜av一区二区| 日本一区二区三区视频一| 99re6在线视频精品免费下载| 国产电影无码午夜在线播放| 亚洲色婷婷综合开心网| 美乳丰满人妻无码视频| 国产精品v欧美精品∨日韩| 国产精品无码无卡在线观看久| 精品国产乱码久久久久APP下载|