这里只谈下平时容易忽视的点。
扁平化处理
promise作为强大的异步解决方法,在最开始使用时往往会陷入到一个误区里面,例如我请求了一个省份id,然后需要省份id去请求市级id,接着还需要市级id获取区县级id。
很多人可能就直接这么写了
//假设使用ajax请求,默认返回的promise对象
function getData() {
api.getProvince().then(provinceId => {
api.getPCCountScriptSummary(provinceId).then(cityId => {
api.getCounty(cityId).then(res => {
// 获取到区县数据
})
})
})
}
刚开始学习promise的时候我也写过这种代码,虽然看似使用了promise,但是依旧是层层嵌套的回调地狱,没有将promise的扁平化特性发挥出来。
代码改造
function getData() {
api.getProvince().then(provinceId => {
return api.getPCCountScriptSummary(provinceId)
}).then(cityId => {
return api.getCounty(cityId)
}).then(res => {
// 获取到区县数据
})
}
这样就达到了promise扁平化代码的特点。
错误捕获
promise里面的错误捕获有两种方式,一种直接放给then方法里面添加第二个参数,一种直接在最后进行catch捕获。
let promiseDemo = new Promise(function(resolve, reject) {
setTimeout(() => {
reject(0)
}, 1000)
})
promiseDemo.then(res => {
console.log(res);
}, err => {
console.log(err, 'reject第二个参数捕获的异常');
}).then(() => {
console.log(1);
}).then(() => {
console.log(2);
})
这样的方式会发先打印出
0 ‘reject第二个参数捕获的异常’
1
2
由此我们可以知道这样的异常捕获不会阻断链式调用。
let promiseDemo = new Promise(function(resolve, reject) {
setTimeout(() => {
reject(0)
}, 1000)
})
promiseDemo.then(res => {
console.log(res);
}).then(() => {
console.log(1);
}).then(() => {
console.log(2);
}).catch(err => {
console.log(err);
})
打印出0,由此可见catch方式捕获异常会直接阻断链式调用。
简单总结下就是reject后的东西,一定会进入then中的第二个回调,如果then中没有写第二个回调,则进入catch,进入catch则代码运行结束。
甚至我们可以进行组合使用
let promiseDemo = new Promise(function(resolve, reject) {
setTimeout(() => {
reject(0)
}, 1000)
})
promiseDemo.then(res => {
console.log(res);
}, err => {
console.log(err, 'reject');
}).then(() => {
reject(1)
}).then(() => {
console.log(2);
}).catch(err => {
console.log(err, 'catch');
})
打印出
0 ‘reject’
1
2
静态方法
简单介绍下promise的几个静态方法
Promise.all
let promiseDemo = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(0)
}, 1000)
})
let promiseDemo1 = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(1)
}, 1000)
})
let promiseDemo2 = new Promise(function(resolve, reject) {
setTimeout(() => {
resolve(2)
}, 1000)
})
Promise.all([promiseDemo, promiseDemo1, promiseDemo2]).then(res => {
console.log(res);
})
简单说就是当所有promise 成功返回就会返回一个结果数组,数组顺序与promise 时的数据一致。若有一个promise 失败则进入catch,并终止剩余promise 。(可以简单理解为promise 的&&操作)
Promise.allSettled
只需将方法替换为allSettled即可
Promise.allSettled([promiseDemo, promiseDemo1, promiseDemo2]).then(res => {
console.log(res);
})
改方法是等待所有promise 结束后,无论成功失败,都会生成一个对象数组,每个对象对应每个promise ,对象里面有两个参数,一个参数是status,表示promise的状态,一个参数是vlaue,表示响应的值。
[
{
status: "fulfilled",
vlaue: "1"
}
]
Promise.any
该方法与Promise.all对应,当其中的一个 promise 成功,就返回那个成功的promise的值。
Promise.race
当其中任何一个promise对象返回结果(无论成功或者失败),则结束执行。
Promise.reject
返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法。
Promise.reject(new Error('fail')).then(function() {
// not called
}, function(error) {
console.error(error); // Stacktrace
});
Promise.resolve
返回一个正确的promise结果,还可以利用此方法将非promise格式的数据转换为promise对象。如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定。
//转换为promise格式
promise.resolve('ok') // Promise {<fulfilled>: 'ok'}
//带then方法的对象
let obj = {
then: function(onFulfilled, onRejected) {
onFulfilled('ok')
}
}
Promise.resolve(obj).then(res => {
console.log(res); // ok
})