直接使用例子来让大家清晰看到Promise的好处
使用Promise 改造异步代码 这一思路,来改造一个常用的ajax
方法:
let $get = function(url) {
return new Promise((resolve, reject) => {
$.get(url, (data, status) => {
if(status === 'success') {
resolve(data);
} else {
reject(data);
}
});
})
}
如果,我们有一连串ajax
请求a, b, c...
,后面的请求依赖于前面请求的结果。
let promise = new Promise((resolve, reject) =>{
//发起 a 请求
return $get('/url_a');
}).then((res) => {
handler_a(res);
// 拿着 a 请求的结果,发起 b 请求
return $get('/url_b?name='+res.name);
})
.then((res) => {
handler_b(res);
// 拿着 b 请求的结果,发起 c 请求
return $get('/url_c?name='+res.name);
})
.then((res) => {
// 处理 c 请求回调
handler_c(res);
})
把我们的目光从函数的具体实现中抽离出来,将函数压缩成一个函数名,每一个异步函数处理自身业务,多个异步函数 “一” 字排开。
let promise = new Promise(fn_a)
.then(fn_b)
.then(fn_c)
.then(callback_c);
没有对比,就没有伤害。我们来看看传统 ES5 的回调办法。
$.get('/url_a', (data, status) => {
handler_a(data);
$.get('/url_b?name='+data.name, (data, status) => {
handler_b(data);
$.get('/url_c?name='+data.name, (data, status) => {
handler_c(data);
});
});
});
层层嵌套,可读性代码差。
promise all的使用
$.get('url_a', function(data){
if(checkAllWith('a')) {
mainRender(data);
}
})
$.get('url_b', function(data){
if(checkAllWith('b')) {
mainRender(data);
}
})
$.get('url_c', function(data){
if(checkAllWith('c')) {
mainRender(data);
}
})
上面代码如果需要请求同一个api的不同数据 那么你就需要发出三个请求
这样的代码是可以解决问题的——如果三个请求都正常返回了,那么排在最后才响应的那个请求,其检验一定会通过,它的回调就会启动全部的渲染。最后一次性将三个模块同时显示出来。反之,任何一个请求无响应,最后都不会启动主渲染。
下面体验all的写法
// $get 是上文中用过的 $.get() 方法的 promise 封装
// $getB、$getC 依次类推
let $getA = function( ) {
return $get('a').then(callback_a);
}
let all = Promise.all([$getA, $getB, $getC]);
// 3 个 promse 全部完成后,才会触发回调
all.then((data) => {
mainRender(data);
})
怎么样,是不是非常简洁。