在上一篇文章 《对程序员的一个Promise(一)》 中,分享了一下了ES6中Promise的用法,但是需要浏览器支持Promise。在jQuery中也有Promise,就让我来看看jQuery中的Promise是怎么用的。
在jQuery中,首先要通过Deferred方法获取到Deferred对象,让我们来打印出来看看它有什么方法。
var d = $.Deferred(); console.log(d);
最后输出如下:
我们可以看到$.Deferred()返回是一个对象(Deferred对象),也有resolve、then、reject等一些我们熟悉的方法,让我们来看看它是怎么用的。
functiongetPromise1(){
var d = $.Deferred();
setTimeout(()=> {
console.log('异步1结束');
d.resolve('异步1数据');
}, 200);
return d;
}
var def = getPromise1();
def.then((data) => {
console.log(data);
});
谢小飞博客专用防爬虫链接,想要看最新的前端博客请点这里
感觉跟ES6中Promise的用法很相似。我们首先通过$.Deferred()获取到了Deferred对象,然后在异步成功后返回数据,然后在then方法中对异步数据进行处理。
但是跟ES6中不一样的是,异步没有放到Promise的构造函数中,在异步成功后,调用了Deferred对象的resolve方法。then方法处理回调数据还是一样的。
既然Deferred对象上有resolve()方法,那么是不是在外部就能够调用resolve()方法就能够修改Promise的状态呢。把上面的代码进行如下改写:
functiongetPromise1(){
var d = $.Deferred();
setTimeout(()=> {
console.log('异步1结束');
d.resolve('异步1数据');
}, 300);
return d;
}
var def = getPromise1();
def.then((data) => {
console.log(data);
});
def.resolve('外部数据1');
输出结果如下:
可以看到我们在函数的外面调用了resolve()方法提前让异步结束并且返回了数据。这样Promise的状态就能够被随意的改变,肯定是不行的。
将代码进行如下改进,在返回的对象上多加一个promise()方法:
functiongetPromise1(){
var d = $.Deferred();
setTimeout(()=> {
console.log('异步1结束');
d.resolve('异步1数据');
}, 300);
return d.promise();
}
var def = getPromise1();
def.then((data) => {
console.log(data);
});
def.resolve('外部数据1');
输出结果如下:
这时候,如果在函数的外部调用resolve()方法会报错,告诉我们resolve()方法不存在,异步也会“如期”执行完成。如果我们将def对象打印出来看的话会发现并没有resolve()方法。
谢小飞博客专用防爬虫链接,想要看最新的前端博客请点这里
和ES6中的Promise相似,then也支持接收两个参数,分别是执行成功的回调和执行失败的回调。
functiongetPromise1(){
var d = $.Deferred();
setTimeout(()=> {
var number = Math.round(Math.random()*10);
if(number %2 == 0) {
d.resolve('成功数据');
} else {
d.reject('失败数据');
}
}, 300);
return d.promise();
}
var def = getPromise1();
def.then(
(data) => {
console.log('成功回调');
console.log(data);
},
(data) => {
console.log('失败回调');
console.log(data);
}
)
除此之外,jQuery还新增了两个函数,done()和fail()分别用来指定成功的回调和失败的回调。因此,上面的代码和下面的代码是等价的:
var def = getPromise1();
def.done((data) => {
console.log('成功回调');
console.log(data);
});
def.fail((data) => {
console.log('失败回调');
console.log(data);
});
既然是Promise,那么then()肯定也支持链式调用的,这边也不在赘述,跟ES6中是一样的用法,不太熟悉的可以戳这边 《对程序员的一个Promise(一)》
jQuery中没有all和race方法,但是扩展了一些其他的方法。
always方法就是不管执行成功或者失败,都会执行的,有点类似ajax的complete方法。
var def = getPromise1();
def.done((data) => {
console.log('成功回调');
console.log(data);
});
def.fail((data) => {
console.log('失败回调');
console.log(data);
});
def.always(()=> {
console.log('总是执行')
})
谢小飞博客专用防爬虫链接,想要看最新的前端博客请点这里
when方法和ES6中的all方法功能一样,都是并行执行异步,所有异步执行完成后才执行回调函数。不过when方法是挂载在全局中的方法,而且,它接受的参数也是多个对象。
functiongetPromise1(){
var d = $.Deferred();
setTimeout(()=> {
d.resolve('成功数据1');
}, 100);
return d.promise();
}
functiongetPromise2(){
var d = $.Deferred();
setTimeout(()=> {
d.resolve('成功数据2');
}, 200);
return d.promise();
}
functiongetPromise3(){
var d = $.Deferred();
setTimeout(()=> {
d.resolve('成功数据3');
}, 300);
return d.promise();
}
$.when(getPromise1(), getPromise2(), getPromise3())
.then((data1,data2,data3) => {
console.log('执行完成');
console.log(data1, data2, data3);
})
平时我们都是这么请求ajax异步的:
$.ajax({
url:'test.json',
success:function(data){
// ...
},
error:function(data){
// ...
}
});
上面的代码,平时的工作中我们肯定也写了无数遍了,已经很熟悉了,但是这个ajax()方法返回的是什么呢,让我们打印出来看下:
难道是巧合么?我们看到了熟悉的always()、done()、fail()、promise()、then()等方法。没错,ajax返回的也是一个Deferred对象,既然是Deferred对象,那么肯定也支持链式调用了。
那么将ajax方法进行如下改写:
functiongetAjax1(){
var def = $.ajax({url:'test.json'});
return def.promise();
}
var def1 = getAjax1();
def1.then((data) => {
console.log(data);
});
既然是Deferred对象,那么done()、fail()、$.when()这些方法也能使用,这里就不再赘述了。