1. 程式人生 > >ES6(promise)_解決回調地獄初體驗

ES6(promise)_解決回調地獄初體驗

tar end err ccf ffffff fun blank 問題 分享

一、前言

通過這個例子對promise解決回調地獄問題有一個初步理解。

二、主要內容

1回調地獄:如下圖所示,一個回調函數裏面嵌套一個回調函數,這樣的代碼可讀性較低也比較惡心

技術分享圖片

2、下面用一個簡單的例子來體驗回調

舉例:我們想要按照順序讀取三個文件,a.txt b.txt c.txt 通過已經學的知識,發現下面的代碼是不行的(代碼是在node環境中實現)

(1)項目目錄結構如下:

技術分享圖片

(2)callback.js: 如下

var fs = require(fs);
//讀取文件a.txt
fs.readFile(./data/a.txt, function (err, data) {
    if (err) {
        throw err
    }

    console.log(data.toString());
})

//讀取文件b.txt fs.readFile(./data/b.txt, function (err, data) { if (err) { throw err } console.log(data.toString()); }) //讀取文件c.txt fs.readFile(./data/c.txt, function (err, data) { if (err) { throw err } console.log(data.toString()); })

(3)測試:發現讀取文件的順序並不是先a.txt --> b.txt -->c.txt,因為這裏讀取文件是異步的,這裏執行的順序取決於文件的大小

技術分享圖片

(4)為了讓讀取的文件按照順序來,我們可以用一下嵌套的方式 ,這種方式可以保證讀取的順序是按照a b c順序來的,,但是代碼嵌套得比較惡心,,這裏只有三層嵌套,

var fs = require(fs);
//讀取a.txt
fs.readFile(./data/a.txt, function (err, data) {
    if (err) {
        throw err
    }

    console.log(data.toString());
//讀取b.txt
    fs.readFile(./data/b.txt, function (err, data) {
    if (err) {
        throw err
    }

    console.log(data.toString());
//讀取c.txt
        fs.readFile(./data/c.txt, function (err, data) {
            if (err) {
                throw err
            }

            console.log(data.toString());
        })

    
})
})

3、使用promise來解決回調嵌套(不了解promise的可以參照阮一峰老師的es6文檔)

var fs = require(fs)

//創建p1的promise容器
var p1 = new Promise(function (resolve, reject) { fs.readFile(./data/a.txt, utf8, function (err, data) { if (err) { reject(err) } else { resolve(data) } }) })
//創建p2的promise容器
var p2 = new Promise(function (resolve, reject) { fs.readFile(./data/b.txt, utf8, function (err, data) { if (err) { reject(err) } else { resolve(data) } }) })
//創建p3的promise容器
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 一個 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) })

為什麽可以那樣做:

技術分享圖片

4、將上面的方法封裝

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

三、總結

參考:阮一峰:http://es6.ruanyifeng.com

ES6(promise)_解決回調地獄初體驗