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) })
三、总结
虽然现在走得很慢,但不会一直这么慢