对于这个概念,是一位朋友无意间提给我的,他问了我一个问题:如果你要同时通过Ajax请求数据,然后判断他们数据是否一样,你会怎么做。身为一只菜鸡,我很给面子的说到:分别用Ajax获得数据再进行比较不就好了?看着他意味深长的笑了,我才意识到事情没有这么简单。
我们来分析一下,通过Ajax请求回来数据的时候,是可能有时间差的,如果你不是全部数据都返回了,就执行判断语句,那肯定会出错的,所以我们必须有个函数,当请求的数据都返回了,再进行比较。这时候就用到了Promise函数。
Promise是ES6的语法,其实在学习react跟vue的时候,已经体会到ES6确实是提供了很多快捷高效的语法,个人觉得抽空学学还是很有必要的。
我学习Promise主要是通过大神们的博客再自己敲敲学到的。其中参考了http://www.hangge.com/blog/cache/detail_1638.html。通过博主的例子,初次体会到了Promise用法。接下来我来讲一下我所学到的Promise。
Promise(function(resolve,reject){})
其中resolve和reject是两个回调方法,什么是回调方法呢,回调方法就是将一个方法func2作为参数传入另一个方法func1中,当func1执行到某一步或者满足某种条件的时候才执行传入的参数func2。现在通过例子来了解下solve和reject。
var a=1;
function log(s){
console.log(s);
}
function cook(){
log("进入cook函数");
var c=new Promise(function(resolve,reject){
if(a==1){
resolve(log("在cook的promise的resolve函数里面"));
}
else{
reject(log("我在cook的promise的reject函数里面"));
a=2;
}
});
return c;
}
function eat(){
log("进入eat函数里面");
var e=new Promise(function(resolve,reject){
log("我在eat的promise里面");
if(a==2){
resolve(log("在eat的promise的resolve函数里面"));
}
else{
reject(log("我在eat的promise的reject函数里面"));
a=3;
}
})
return e;
}
function wash(){
log("进入wash函数里面");
var w=new Promise(function(resolve,reject){
log("我在wash的promise里面");
if(a==3){
resolve(log("在wash的promise的resolve函数里面"));
}
else{
reject(log("我在wash的promise的reject函数里面"));
a=4;
}
})
return w;
}
// cook().then(eat).then(wash);
cook().then(eat).then(wash).catch(function(data){
log(data)
});
在cook、eat、wash函数 定义了promise要返回,不然在链式调用的时候回报错Cannot read property 'then' of undefined
以上代码的结果,可以看出,进入cook函数后,判断a=1,然后执行了resolve方法。当进入了eat函数后,a!=2,那么执行reject方法,执行了reject方法后,我们不会再进行往下的链式调用。
将代码的判断条件改一下
var a=1;
function log(s){
console.log(s);
}
function cook(){
log("进入cook函数");
var c=new Promise(function(resolve,reject){
if(a==1){
resolve(log("在cook的promise的resolve函数里面"));
a=2;
}
else{
reject(log("我在cook的promise的reject函数里面"));
}
});
return c;
}
function eat(){
log("进入eat函数里面");
var e=new Promise(function(resolve,reject){
log("我在eat的promise里面");
if(a==2){
resolve(log("在eat的promise的resolve函数里面"));
a=3;
}
else{
reject(log("我在eat的promise的reject函数里面"));
}
})
return e;
}
function wash(){
log("进入wash函数里面");
var w=new Promise(function(resolve,reject){
log("我在wash的promise里面");
if(a==3){
resolve(log("在wash的promise的resolve函数里面"));
a=4;
}
else{
reject(log("我在wash的promise的reject函数里面"));
}
})
return w;
}
// cook().then(eat).then(wash);
cook().then(eat).then(wash).catch(function(data){
log(data)
});
可以看出,如果满足条件,那个就会一直往下执行。
all()方法
promise有个all方法,可以执行所有传入的方法后再调用最后的方法。
我们改一下代码的链式调用一块以及cook的代码 cook函数的resolve方法中不给a赋值
Promise.all([cook(),eat(),wash()]).then(function(data){
log("全部代码都执行完")
}).catch(function(){
log("有代码出错啦")
})
可以看出cook、eat、wash方法都执行一遍报错了,在链式那里catch到,并报告出错
race()方法
这个方法跟all很相似,不过all是会执行所有的方法才会then回调,race方法是只要有一个异步操作执行完毕,就立刻执行 then 回调。注意:其它没有执行完毕的异步操作仍然会继续执行,而不是停止。我们给eat方法加了定时器
function eat(){
log("进入eat函数里面");
var e=new Promise(function(resolve,reject){
log("我在eat的promise里面");
if(a==2){
setTimeout(function(){
resolve(log("在eat的promise的resolve函数里面2"))
},1000);
}
else{
reject(log("我在eat的promise的reject函数里面1"));
}
})
return e;
}
Promise.race([cook(),eat(),wash()]).then(function(){
log("有方法执行完")
}).catch(function(){
log("有方法出错啦")
})
知道这些方法后,我们开始做之前说的对比两个数据。
var a="";
var b="";
function ajax1(){
console.log("enter ajax1");
var promise1=new Promise(function(resolve,reject){
console.log("enter promise1");
$.ajax({
type:"get",
url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+"a",
dataType:"jsonp",
jsonp:"cb",
success:function(data){
// console.log(data.s[0])
a=data.s[0];
resolve(a);
},
error:function(error){
reject("ajax1 error")
}
});
});
return promise1;
}
function ajax2(){
console.log("enter ajax2");
var promise2=new Promise(function(resolve,reject){
console.log("enter promise2");
$.ajax({
type:"get",
url:"https://sp0.baidu.com/5a1Fazu8AA54nxGko9WTAnF6hhy/su?wd="+"a",
dataType:"jsonp",
jsonp:"cb",
success:function(data){
// console.log(data.s[0])
b=data.s[0];
resolve(b);
},
error:function(error){
reject("ajax2 error")
}
})
});
return promise2;
}
function compare(){
if(a!=b){
console.log("different")
}
else{
console.log("same")
}
}
ajax1().then(ajax2).then(compare).then(function(data){
console.log(data)
});
在上述代码有有两个ajax方法来去百度引擎的数据,取回来后将数据进行对比,在链式调用中,先取ajax1数据后,进行取ajax2数据,之后再进行对比,得出结果。
代码我都放在github上,有兴趣的小伙伴可以看看
https://github.com/LittleBeautyMX/javascript-demo
有什么不对的地方,欢迎留言批评改正