ES6 Promise的应用场景及注意事项
场景一:
需求:通过接口1得到的结果为参数调用接口二,使用接口二得到的数据作为参数调用接口三,最后返回接口三的数据。代码如下:
//模拟接口
let fakeInterface = (url, param) => {
return new Promise((resolve, reject) => {
setTimeout(() => { //模拟一个异步的接口
//想让哪个接口报错(走reject)就把indexOf改为那个接口的url,此处不想让任何报错就使用了不存在的url
url.indexOf('接口四') < 0 ? resolve(url + param) : reject(url + '错误');
}, 1000);
});
};
//开始调用
fakeInterface('接口一', 1)
.then(data => {
console.log(data);
return fakeInterface('接口二', data);
})
.then(data => {
console.log(data);
return fakeInterface('接口三', data);
})
.then(data => {
console.log(data);
//在这里对最终获得的数据进行你想要的操作。
//在pormise中return的所有数据都会被自动包裹在promise里,因此即使你return data,也是没有意义的,最终还是要通过.then获取。
})
.catch(err => {
console.log(err);
})
输出结果如下
如果你想让第二个接口走reject,可以将url.indexOf(‘接口四’) 改为url.indexOf(‘接口二’),获得的输出如下:
注意:此时的接口三并没有输出,也就是说如果在三个模拟接口中任意一个出发了reject,后面的都不会执行。
场景二:
需求:在场景一的基础之上,如果三个接口中的任意一个接口报错,则将报错信息为参数,调取一个接口,再将获得的数据返回。
//模拟接口
let fakeInterface = (url, param,errkey) => {
return new Promise((resolve, reject,) => {
setTimeout(() => { //模拟一个异步的接口
//想让哪个接口报错(走reject)就把indexOf改为那个接口的url,此处不想让任何报错就使用了不存在的url
if(errkey){
resolve({
errkey,
mes:param+'后获得的数据'
})
}else{
url.indexOf('接口二') < 0 ? resolve(url + param) : reject(url + '错误');
}
}, 1000);
});
};
//开始调用
fakeInterface('接口一', 1)
.then(data => {
console.log(data);
return fakeInterface('接口二', data);
})
.then(data => {
console.log(data);
return fakeInterface('接口三', data);
})
.then(data => {
console.log(data);
return data;
})
.catch(err => {
console.log(err);
return fakeInterface('如果发生错误的接口', err,1);
})
.then(data => {//这个.then无论如何都会执行,即使接口一报错了,在执行完.catch之后就会执行该.then,如果没有接口报错,会最后一个执行该.then
//如果没通过.catch过来,data为接口三获取到的字符串数据,string.mes为undefined,并不会出现浏览器报错,只有在undefined.mes才会浏览器报错抛出异常
if(data.mes){
console.log(data.mes);
return data.mes
}else{
return data
}
})
输出结果如下:
其实此处使用async await处理更加合适,只是在此处展示一下promise的处理方式,
注意点!!!:一下是关于在.then 或.catch内return的问题:
不管是.then 还是.catch 都是可以不断的使用.then 链式调用的,因为不管如何,即使你不在.then或者.catch中return,它都会自己返回一个resolve为undefined的promise对象。并且不管你return的是什么东西,都会被一个promise对象包裹,(有些小机灵鬼可能会问了,如果我返回的是一个promise对象呢,那会不会最后返回的是一个promise包裹我return的promise,你自己试一下就知道了,其实还是一层,如果你返回的是promise他就不会再给你套一层了)
场景三
需求:同时请求三个接口,在最慢的接口获取到数据后,将三个接口获得到的值进行计算再做为参数,请求接口四,最后返回接口四的数据。
//模拟接口
let fakeInterface = (url, param, ms) => {//ms为模拟接口时间
return new Promise((resolve, reject, ) => {
setTimeout(() => { //模拟一个异步的接口
//想让哪个接口报错(走reject)就把indexOf改为那个接口的url,此处不想让任何报错就使用了不存在的url
url.indexOf('无') < 0 ? resolve(url + param) : reject(url + '错误');
}, ms);
});
};
Promise.all([fakeInterface('接口一', 1,1000),fakeInterface('接口二', 2,2000),fakeInterface('接口三', 3,3000)])
.then(data=>{
console.log(data);//3秒才打印出 结果为:["接口一1", "接口二2", "接口三3"]
return fakeInterface('接口四',data.join('-'),1000);
})
.then(data=>{
console.log(data);
return data;
})
.catch(err=>{
console.log(err);
})
输出结果为:
如果让接口二报错,(即将url.indexOf(‘无’)改为url.indexOf(‘二’))输出如下
场景四
需求:同时请求三个接口,在最快的接口获取到数据后,即返回最快接口获得的数据。
//模拟接口
let fakeInterface = (url, param, ms) => {//ms为模拟接口时间
return new Promise((resolve, reject, ) => {
setTimeout(() => { //模拟一个异步的接口
//想让哪个接口报错(走reject)就把indexOf改为那个接口的url,此处不想让任何报错就使用了不存在的url
url.indexOf('无') < 0 ? resolve(url + param) : reject(url + '错误');
}, ms);
});
};
Promise.race([fakeInterface('接口一', 1,2000),fakeInterface('接口二', 2,1000),fakeInterface('接口三', 3,3000)])
.then(data=>{
console.log(data);//1秒才印出 结果为:"接口二2"
})
.catch(err=>{
console.log(err);
})
输出结果为:
注意:Promise.race只要有一个接口返回结果,其他的promise里即使出现了reject也会忽略,但如果最快的接口返回了reject,则会进入jeject。例如将url.indexOf(‘无’)改为url.indexOf(‘接口一’)或url.indexOf(‘接口三’)并不会与之前有任何区别。