文章目录
如何使用promise
一般来说,我们处理异步事件都时候都是函数里面套函数,但是这样不仅不美观而且可读性非常差,就出现了回调地狱
的问题
fs.readdir(source, function (err, files) {
if (err) {
console.log('Error finding files: ' + err)
} else {
files.forEach(function (filename, fileIndex) {
console.log(filename)
gm(source + filename).size(function (err, values) {
if (err) {
console.log('Error identifying file size: ' + err)
} else {
console.log(filename + ' : ' + values)
aspect = (values.width / values.height)
widths.forEach(function (width, widthIndex) {
height = Math.round(width / aspect)
console.log('resizing ' + filename + 'to ' + height + 'x' + height)
this.resize(width, height).write(dest + 'w' + width + '_' + filename, function(err) {
if (err) console.log('Error writing file: ' + err)
})
}.bind(this))
}
})
})
}
})
为了解决这个问题,ES6增加的promise
函数就是一个异步回调的语法糖。
使用promise
let p = new Promise(function (resolve,rej) {
fs.readdir(source, function (err, files) {
if(err) {
// 执行错误
rej(err)
} {
// 执行成功回调函数
resolve(files)
}
})
})
p.then(function(data){
// 执行成功回调函数
},function(err){
// 执行错误回调函数
console.log('Error finding files: ' + err)
})
// 这里可以使用catch,这样then就可以值接受成功回调函数
p.then(function(data){
// 成功回调函数
}).catch(fucntion(err){
console.log('Error finding files: ' + err)
})
需要知道是
promise
的方法都是可以链式回调的
除此之外,promise
还有其他方法,建议阅读官方Promise MDN
Promise.all()
个人定义:这个是检测输入的一个Promise
的实例数组,如果有一个返回错误的回调,则全部停止,进行错误回调函数执行
官方解释”Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败原因的是第一个失败 promise 的结果。
var p1 = new Promise(function(res,rej){
res('p1')
})
var p2 = 45
var p3 = Promise.resolve(3); // Promise.resolve(value)方法返回一个以给定值解析后的Promise 对象。
Promise.all([p1,p2,p3]).then((value)=>{
console.log(value) console.log(values); // [“p1”, 45, 3]
})
// 输出 p1 45 3
这里p2
为什么能够输出45?
从官方解释获取答案
iterable是一个可迭代对象,如 Array 或 String。
如果参数中包含非 promise 值,这些值将被忽略,但仍然会被直接放在返回数组中(如果 所有输入的 promise
完成的话)
Promise.allSettled
allSettled
:全部被设置。统一设置回调函数,如果我们需要对2个Promise
进行相同的回调处理的时候,我们可以将他们进行合并,同时设置。
const promise1 = Promise.resolve(3); // 成功
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));// 失败
Promise.allSettled([promise1, promise2]).
then((results) =>
results.forEach((result) => console.log(result.status)));// 输出异步处理结果
// expected output:
// "fulfilled"
// "rejected"
这里输出的是promise
的状态,我们可以先了解下promise
有三种状态
pending
处理中fulfilled
成功回调rejected
失败回调
3.Promise.resolve()
和Promise.reject()
这个返回设置好的成功回调或者失败回调的Promise
对象,而参数输入的是解析之后返回的解析结果,如果你设置之后再次设置then
的话,则会跟踪到对应的参数
var promise1 = Promise.resolve(123);
promise1.then(function(value) {
console.log(value);
// expected output: 123
});
不可以在自身的thenable 上调用Promise.resolve。这将导致无限递归,因为它试图展平无限嵌套的promise。
4. Promise.race([promise1,promise2……])
一旦参数中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
var promise1 = new Promise(function(resolve, reject) {
setTimeout(resolve, 500, 'one');
});
var promise2 = new Promise(function(resolve, reject) {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then(function(value) {
console.log(value);
// 2个都是成功函数回调,但是promise2更加快
});
// 输出 2
就是输入的多个promise
,只会进行处理第一个成功或者失败的promise
。
这个可以用在多个请求,但是我们只需要其中一个请求即可,所以可以使用race
来进行异步请求,如果失败则重新请求,成功了就执行成功回调函数,这样就可以尽可能快速获得请求数据。因为他直接接受完成最快的异步请求。
5.Promise.finaly(function)
这个设置的时无论成功与否都会调用的函数。
使用过程的问题
关于链式
var p1 = new Promise((res,rej)=>{
res(11)
})
p1.then((data)=>{
console.log(data) // 11
}).then(
(data)=>{console.log(data)// undefined
})
输出结果
11
undefined
这里可以链式调用,因为then
返回的是一个Promise
对象,所以可以调用then
,但是我们并不能多次获取到data
值,因为then
设置的回调是一个全新的Promise
所以和前面无关,但是我们可以通过自己设置返回Promise
来进行异步里面套异步
var p1 = new Promise((res,rej)=>{
res('一次回调')
})
p1.then((data)=>{
console.log(data) // 一次回调
// return p1
return new Promise((res,rej)=>{
res('二次回调')
})
}).then(
(data)=>{console.log(data) // 二次回调
})
输出结果
一次回调
二次回调
这里为什么返回一个新的Promise
就可以实现异步嵌套呢?
这就是Promise
设计的高明之处。我们在下一章来讨论这个问题。