在开发JavaScript过程中,我们经常会用到异步操作和回调函数,但是,我们都知道,异步操作不能保证执行顺序是我们想象的那样,所以,就出现了“回调地狱”。
举个栗子:比如我现在要读取三个文件a.txt,b.txt,c.txt,并且让他的执行顺序必须为“先a,后b,最后c”,显然,我们不能用下面这种方法
var fs = require('fs')
fs.readFile('./data/a.txt','utf8',function (err, data) {
if (err) {
throw err
}
console.log(data)
})
fs.readFile('./data/b.txt','utf8',function (err, data) {
if (err) {
throw err
}
console.log(data)
})
fs.readFile('./data/c.txt','utf8',function (err, data) {
if (err) {
throw err
}
console.log(data)
})
执行结果:
我们执行多次,会发现,执行顺序是随机的,也就是说,他并不能像我们所想的一样,从上到下执行。
所以,我们一般会采用这种方式:
var fs = require('fs')
fs.readFile('./data/a.txt','utf8',function (err, data) {
if (err) {
throw err
}
console.log(data)
fs.readFile('./data/b.txt','utf8',function (err, data) {
if (err) {
throw err
}
console.log(data)
fs.readFile('./data/c.txt','utf8',function (err, data) {
if (err) {
throw err
}
console.log(data)
})
})
})
使用这样的方法,程序的执行顺序永远都是 “a,b,c” 。
但是,当我们必须要执行很多异步方法又必须保证顺序一定时,我们就有机会写出这样的代码:
怎么样?是不是感觉,很不美观,而且,在维护的时候,有可能一脸懵逼。
为了解决这个问题,ES6中的 promise 便可以“优雅”的解决这个问题了。
还是上面相同的案例,如果,我们用promise来重构的话,会变成这样。
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)
})
怎么样,是不是感觉,结构一下清晰了很多。
每一个方法相对“独立”,按照一定的顺序执行,而且改变执行顺序也变的简单了很多。