ES6(promise)_解決回調地獄初體驗
一、前言
通過這個例子對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)_解決回調地獄初體驗