1、为什么会有promise
这里我不阐述什么特别详细的概念,直接以实际需求出发。
现在手上的问题是,前端需要用echarts构建一个图表,而数据是通过ajax请求rest的数据接口而来的,但是echarts绘图需要的数据需要同时请求到多个数据源,
才能完整的将图表画出来。常规的写法是,JavaScript的函数回调,也就是下面的代码:
ajax 函数回调:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ajax 回调形式</title>
</head>
<body>
</body>
<script src="../../../vender/jquery.js"></script>
<script>
$.ajax({
type: "GET",
url: "rest1",
success: function(res){
//接口rest1 的数据请求成功,接着去请求rest2 的数据
var rest1Data = res;
$.ajax({
type: "GET",
url: "rest2",
success: function(res){
var rest2Data = res;
//使用数据rest1Data 和 rest2Data 绘图表
drawGraph(rest1Data,rest2Data);
}
});
}
});
</script>
</html>
看了上面的代码就给人一种想吐的冲动,不说写起来繁杂,而且还没技术含量,总之就是不上档次,而且现在是两个数据源,如果是多个数据源难道要一直的嵌套下去?
没办法,为了装逼,我不得不开始骚扰度娘。。。于是我找到了commonjs提出的promise 编程理念,瞬间感觉世界有爱了,有木有?!
2.什么是promise
promise编程,个人理解就是,同步编程,异步执行。通过一个deferred延迟对象,帮我们搞定所有的事情,你敢信?哈哈,不得不信啊。。。
关于promise一些基础概念,自行百度下吧,骚年,下面我直接使用jQuery的promise来实现,上代码:
$.ajax("rest1").done(function (res) {
var res1Data = res;
//请求rest2的数据<span style="white-space:pre"> </span>
$.ajax("rest1").done(function (res) {
var res2Data = res;
//绘图表
drawGraph(res1Data,res2Data)
})
})
.fail(function () {
alert("出错啦!");
})
.done(function () {
alert("第二个回调函数!");
});
如果你在这段时间已经看了jquery的延迟对象相关的概念,肯定会发现还有$.when()这个牛逼的方法,所以我们的代码可以改写成如下方式:
$.when($.ajax("rest1"), $.ajax("rest2"))
.done(function(v1,v2){
var rest1Data = v1[0].data;
var rest2Data = v1[1].data;
//绘图表
drawGraph();
})
.fail(function(){ alert("出错啦!"); });
解释一些吧:
$.when() 的方法参数 为 延迟对象,可以为多个,$.ajax() 方法调用后返回的即是一个promise对象,ajax调用后对应返回的数据,封装到done方法的回调函数中的参数中,也就是时上述的v1,v2对象。
3.promise的进阶
上述说了半天只是为了解决我实际遇到的问题,但有时候我们需要的不是ajax的请求,而是普通的函数回调,有点绕啊,没事,我举例子,呵呵!
加入说我们声明了一个回调函数,这个函数很耗时,比如:
var wait = function(){
var tasks = function(){
alert("执行完毕!");
};
setTimeout(tasks,5000);
};
var dtd = $.Deferred(); // 生成Deferred对象
var wait = function(dtd){
var tasks = function(){
alert("执行完毕!");
dtd.resolve(); // 改变Deferred对象的执行状态
};
setTimeout(tasks,5000);
};
dtd.promise(wait);
wait.done(function(){ alert("哈哈,成功了!"); })
.fail(function(){ alert("出错啦!"); });
wait(dtd);
解释一些吧:
1、首先声明一个defferd对象,
2、在声明wait()函数时,虽然很耗时,但我们在函数执行完时,通过deferred对象返回一个promise对象,
3、接下来,我们就可以调用jQuery给我们提供的关于pomise的一系列API了
4.jQuery中的defered的一些API总结:
(1) $.Deferred() 生成一个deferred对象
(2) deferred.done() 指定操作成功时的回调函数
(3) deferred.fail() 指定操作失败的回调韩式
(4) deferred.promise() 没有参数时,返回一个新的deferred对象,该对象的运行状态无法改变:接受参数时,作用为在参数对象上部署到deffered接口上
(5) deferred.resolve() 手动改变deffered对象的运行状态“已完成”,从而触发done()方法
(6) deferred.reject() 这个方法与deffered.resolve()正好相反,调用后将deffered对象的运行状态改变为“已失败”,从而立即触发fail()方法
(7) $.when() 为多个操作指定回调函数,参数为多个deffered对象
(8) deferred.then() 可以整合done()和fail()
$.when($.ajax('rest')).then(successFunc, failFunc);
(9) deferred.always() 这个方法也是用来指定回调函数的,它的作用是,不管调用的是deferred.resolve()还是deferred.reject(),最后总是执行。
$.ajax( "test.html" ).always( function() { alert("已执行!");} );
5.最后的最后。。。
写到这,也算是解决问题了,不过笔者已有未尽,最后和大家聊聊现在比较火的angular中promise实现,主要是$q, 这个服务,算了,不聊了,还是直接上代码
var q1 = $.get('rest1');
var q2 = $.get('rest2');
$q.all([q1,q2]).then(function(res){
var res1Data = res[0].data;
var res2Data = res[0].data;
//绘图表
drawGraph();
});