- 首先大家按照大家已有的知识点来思考一下如何解决呢?
代码如下:
$(function(){
var arr = []
$.get("https://cnodejs.org/api/v1/topics?tab=ask",function(data){
arr.push(data);
$.get("https://cnodejs.org/api/v1/topics?tab=job",function(data){
arr.push(data);
$.get("https://cnodejs.org/api/v1/topics?tab=good",function(data){
arr.push(data);
$.get("https://cnodejs.org/api/v1/topics?tab=share",function(data){
arr.push(data);
console.log(arr)
})
})
})
})
})
简称 回调地狱
缺点耗费时间,看图说话:
之前我们可能会用解决方法。
(function () {
var count = 0;
var arr = [];
function handle() {
if (count === 4) {
console.log(arr);
}
}
$.get("https://cnodejs.org/api/v1/topics?tab=good",function(data){
arr.push(data);
count++;
handle()
})
$.get("https://cnodejs.org/api/v1/topics?tab=job",function(data){
arr.push(data);
count++;
handle()
})
$.get("https://cnodejs.org/api/v1/topics?tab=share",function(data){
arr.push(data);
count++;
handle()
});
$.get("https://cnodejs.org/api/v1/topics?tab=ask",function(data){
arr.push(data);
count++;
handle()
});
})();
但是这种依然有个缺点,得写监控函数,每次回调都会调用监控函数,耗费性能,还有其他方法吗?
查看network 中的waterfall;
Promise 来了,用promise怎么实现呢?
代码如下:
$(function(){
// 封装一个promise;将url提取出来;
var p = function(url){
return new Promise(function(resolve,reject){
$.get(url,function(data){
resolve(data);
})
})
}
Promise.all([
p("https://cnodejs.org/api/v1/topics?tab=good"),
p("https://cnodejs.org/api/v1/topics?tab=share"),
p("https://cnodejs.org/api/v1/topics?tab=ask"),
p("https://cnodejs.org/api/v1/topics?tab=job"),
]).then(function(result){
console.log(result);
})
})
waterfall图如下:
有的时候有这样的需求,后面的ajax请求依赖前面的ajax请求必须按照顺序调动如何实现呢?
前面的回调是一种解决方案,但是想避免回调地狱的写法用promise实现顺序调用呢?
$(function(){
// 封装一个promise;
var p = function(url){
return new Promise(function(resolve,reject){
$.get(url,function(data){
resolve(data);
})
})
}
var arr = []
p("https://cnodejs.org/api/v1/topics?tab=ask")
.then(function(data){
arr.push(data);
return p("https://cnodejs.org/api/v1/topics?tab=share")
}).then(function(data){
arr.push(data);
return p("https://cnodejs.org/api/v1/topics?tab=ask")
}).then(function(data){
arr.push(data);
return p("https://cnodejs.org/api/v1/topics?tab=good")
}).then(function(data){
arr.push(data);
console.log(arr);
})
})
waterfall执行图:
再看一个应用场景:
请求多个资源,哪个接口先返回,就处理哪个接口的信息:
一般应用的比较多的是分布式应用,举例子说明,
四台 服务器分别位于 北京 上海 南京 郑州:画图说明
这应用到一个race接口,将4.html的js代码改成如下:
$(function(){
// 封装一个promise;
var p = function(url){
return new Promise(function(resolve,reject){
$.get(url,function(data){
resolve(data);
})
})
}
Promise.race([
p("https://cnodejs.org/api/v1/topics?tab=good"),
p("https://cnodejs.org/api/v1/topics?tab=share"),
p("https://cnodejs.org/api/v1/topics?tab=ask"),
p("https://cnodejs.org/api/v1/topics?tab=job"),
]).then(function(result){
console.log(result);
})
})
运行看结果,谁最先返回就打印谁的数据:
再来看一个需求,发送一个请求,请求超时后返回特定信息如何实现:
jquery版本:
$.ajax({
url:'https://cnodejs.org/api/v1/topics?tab=good', //请求的URL
timeout : 1000, //超时时间设置,单位毫秒
type : 'get', //请求方式,get或post
data :{}, //请求所传参数,json格式
dataType:'json',//返回的数据格式
success:function(data){ //请求成功的回调函数
alert("成功");
},
error:function(){
console.log("超时了")
}
});
//设置timeout的时间,超时后触发error函数。
Promise版本如何实现呢?
- 封装两个Promise
- 一个promise里面封装ajax请求
- 一个Promise封装定时器
- 调用Promise类的race方法
- 链式调用then方法获得执行结果。
注意:Promise.race的参数为一个数组,数组每一项都是promise实例对象。
Promise.race的返回结果为一个Prmise实例,只不过这个实例只能是最先执行resolve的那个promise。
$(function(){
// 封装一个promise;
var p = function(url){
return new Promise(function(resolve,reject){
$.get(url,function(data){
resolve(data);
})
})
}
var p2 = function(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve('请求超时了')
},100)
})
}
Promise.race([
p("https://cnodejs.org/api/v1/topics?tab=good"),
p2()
]).then(function(result){
console.log(result);
})
})
promise捕获错误的使用.
如何捕获promise的错误呢?在promise的调用链的最后调用catch函数,一旦promise调用链中有reject执行,promise就会终止执行直接进入catch函数,否则catch不会执行。
$(function(){
// 封装一个promise;
var p = function(url){
return new Promise(function(resolve,reject){
$.get(url,function(data){
resolve(data);
})
})
}
## 最后
今天的文章可谓是积蓄了我这几年来的应聘和面试经历总结出来的经验,干货满满呀!如果你能够一直坚持看到这儿,那么首先我还是十分佩服你的毅力的。不过光是看完而不去付出行动,或者直接进入你的收藏夹里吃灰,那么我写这篇文章就没多大意义了。所以看完之后,还是多多行动起来吧!
可以非常负责地说,如果你能够坚持把我上面列举的内容都一个不拉地看完并且全部消化为自己的知识的话,那么你就至少已经达到了中级开发工程师以上的水平,进入大厂技术这块是基本没有什么问题的了。