1. 程式人生 > >Es6中的promise解決callback hell回撥地獄問題及示例程式碼

Es6中的promise解決callback hell回撥地獄問題及示例程式碼

1.js中多個非同步呼叫(介面,讀取檔案)時沒有順序,若業務現在要求有順序的呼叫,就只能巢狀回撥,如果巢狀回撥3個以下程式碼量還不是很多,還可以湊乎,超過3個後重復程式碼多,可維護性差,程式碼醜陋ugly,就造成了callback hell,所以Es6出了promise解決此問題,jquery支援promise功能,node中的mongoose支援。

使用場景:註冊功能前查詢使用者名稱字是否存在,手機號是否存在等等,頁面的select多級聯動(查詢省市縣)下拉框選擇後還需要查詢資料。

示例程式碼:

var fs = require('fs')

fs.readFile('./data/a.txt', 'utf8', function (err, data) {
  if (err) {
    // return console.log('讀取失敗')
    // 丟擲異常
    //    1. 阻止程式的執行
    //    2. 把錯誤訊息列印到控制檯
    throw err
  }
  console.log(data)
  fs.readFile('./data/b.txt', 'utf8', function (err, data) {
    if (err) {
      // return console.log('讀取失敗')
      // 丟擲異常
      //    1. 阻止程式的執行
      //    2. 把錯誤訊息列印到控制檯
      throw err
    }
    console.log(data)
    fs.readFile('./data/c.txt', 'utf8', function (err, data) {
      if (err) {
        // return console.log('讀取失敗')
        // 丟擲異常
        //    1. 阻止程式的執行
        //    2. 把錯誤訊息列印到控制檯
        throw err
      }
      console.log(data)
    })
  })
})

 promise容器概念:pending正在進行後有2種狀態,要麼成功變成resolved,要麼失敗變成rejected.

 

promiseAPI程式碼圖示:

 promise的鏈式呼叫

1.示例程式碼:

1)使用promise未封裝url版本

var fs = require('fs')

var p1 = new Promise(function (resolve, reject) {
  fs.readFile('./data/a.txt', 'utf8', function (err, data) {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})

var p2 = new Promise(function (resolve, reject) {
  fs.readFile('./data/b.txt', 'utf8', function (err, data) {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})

var p3 = new Promise(function (resolve, reject) {
  fs.readFile('./data/c.txt', 'utf8', function (err, data) {
    if (err) {
      reject(err)
    } else {
      resolve(data)
    }
  })
})

p1
  .then(function (data) {
    console.log(data)
    // 當 p1 讀取成功的時候
    // 當前函式中 return 的結果就可以在後面的 then 中 function 接收到
    // 當你 return 123 後面就接收到 123
    //      return 'hello' 後面就接收到 'hello'
    //      沒有 return 後面收到的就是 undefined
    // 上面那些 return 的資料沒什麼卵用
    // 真正有用的是:我們可以 return 一個 Promise 物件
    // 當 return 一個 Promise 物件的時候,後續的 then 中的 方法的第一個引數會作為 p2 的 resolve
    //
    return p2
  }, function (err) {
    console.log('讀取檔案失敗了', err)
  })
  .then(function (data) {
    console.log(data)
    return p3
  })
  .then(function (data) {
    console.log(data)
    console.log('end')
  })

 2)使用promise封裝url後版本

var fs = require('fs')

function pReadFile(filePath) {
  return new Promise(function (resolve, reject) {
    fs.readFile(filePath, 'utf8', function (err, data) {
      if (err) {
        reject(err)
      } else {
        resolve(data)
      }
    })
  })
}

pReadFile('./data/a.txt')
  .then(function (data) {
    console.log(data)
    return pReadFile('./data/b.txt')
  })
  .then(function (data) {
    console.log(data)
    return pReadFile('./data/c.txt')
  })
  .then(function (data) {
    console.log(data)
  })