Skip to content

Commit 40d4d50

Browse files
committed
update
1 parent 9b4f7a2 commit 40d4d50

File tree

3 files changed

+257
-9
lines changed

3 files changed

+257
-9
lines changed

part2-jquery/02-jquery-deferred.md

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
# jQuery deferred
2+
3+
上一节讲到 jquery v1.5 版本开始,`$.ajax`可以使用类似当前`Promise``then`函数以及链式操作。那么它到底是如何实现的呢?在此之前所用到的`callback`在这其中又起到了什么作用?本节给出答案
4+
5+
本节使用的代码参见[这里](./test.html)
6+
7+
## 本节内容概述
8+
9+
- 写一个传统的异步操作
10+
- 使用`$.Deferred`封装
11+
- 应用`then`方法
12+
- 有什么问题?
13+
14+
## 写一个传统的异步操作
15+
16+
给出一段非常简单的异步操作代码,使用`setTimeout`函数。
17+
18+
```javascript
19+
var wait = function () {
20+
var task = function () {
21+
console.log('执行完成')
22+
}
23+
setTimeout(task, 2000)
24+
}
25+
wait()
26+
```
27+
28+
以上这些代码执行的结果大家应该都比较明确了,即 2s 之后打印出`执行完成`**但是我如果再加一个需求 ———— 要在执行完成之后进行某些特别复杂的操作,代码可能会很多,而且分好几个步骤 ———— 那该怎么办?** 大家思考一下!
29+
30+
如果你不看下面的内容,而且目前还没有`Promise`的这个思维,那估计你会说:直接在`task`函数中写就是了!不过相信你看完下面的内容之后,会放弃你现在的想法。
31+
32+
## 使用`$.Deferred`封装
33+
34+
好,接下来我们让刚才简单的几行代码变得更加复杂。**为何要变得更加复杂?是因为让以后更加复杂的地方变得简单**。这里我们使用了 jquery 的`$.Deferred`,至于这个是个什么鬼,大家先不用关心,**只需要知道`$.Deferred()`会返回一个`deferred`对象**,先看代码,`deferred`对象的作用我们会面会说。
35+
36+
```javascript
37+
function waitHandle() {
38+
var dtd = $.Deferred() // 创建一个 deferred 对象
39+
40+
var wait = function (dtd) { // 要求传入一个 deferred 对象
41+
var task = function () {
42+
console.log('执行完成')
43+
dtd.resolve() // 表示异步任务已经完成
44+
}
45+
setTimeout(task, 2000)
46+
return dtd // 要求返回 deferred 对象
47+
}
48+
49+
// 注意,这里一定要有返回值
50+
return wait(dtd)
51+
}
52+
```
53+
54+
以上代码中,又使用一个`waitHandle`方法对`wait`方法进行再次的封装。`waitHandle`内部代码,我们分步骤来分析。跟着我的节奏慢慢来,保证你不会乱。
55+
56+
- 使用`var dtd = $.Deferred()`创建`deferred`对象。通过上一节我们知道,一个`deferred`对象会有`done` `fail``then`方法(不明白的去看上一节)
57+
- 重新定义`wait`函数,但是:第一,要传入一个`deferred`对象(`dtd`参数);第二,当`task`函数(即`callback`)执行完成之后,要执行`dtd.resolve()`告诉传入的`deferred`对象,革命已经成功。第三;将这个`deferred`对象返回。
58+
- 返回`wait(dtd)`的执行结果。因为`wait`函数中返回的是一个`deferred`对象(`dtd`参数),因此`wait(dtd)`返回的就是`dtd`————如果你感觉这里很乱,没关系,慢慢捋,一行一行看,相信两三分钟就能捋顺!
59+
60+
最后总结一下,`waitHandle`函数最终`return wait(dtd)`即最终返回`dtd`(一个`deferred`)对象。针对一个`deferred`对象,它有`done` `fail``then`方法(上一节说过),它还有`resolve()`方法(其实和`resolve`相对的还有一个`reject`方法,后面会提到)
61+
62+
63+
## 应用`then`方法
64+
65+
接着上面的代码继续写
66+
67+
```javascript
68+
var w = waitHandle()
69+
w.then(function () {
70+
console.log('ok 1')
71+
}, function () {
72+
console.log('err 1')
73+
}).then(function () {
74+
console.log('ok 2')
75+
}, function () {
76+
console.log('err 2')
77+
})
78+
```
79+
80+
上面已经说过,`waitHandle`函数最终返回一个`deferred`对象,而`deferred`对象具有`done` `fail` `then`方法,现在我们正在使用的是`then`方法。至于`then`方法的作用,我们上一节已经讲过了,不明白的同学抓紧回去补课。
81+
82+
执行这段代码,我们打印出来以下结果。可以将结果对标以下代码时哪一行。
83+
84+
```
85+
执行完成
86+
ok 1
87+
ok 2
88+
```
89+
90+
此时,你再回头想想我刚才说提出的需求(*要在执行完成之后进行某些特别复杂的操作,代码可能会很多,而且分好几个步骤*),是不是有更好的解决方案了?
91+
92+
有同学肯定发现了,代码中`console.log('err 1')``console.log('err 2')`什么时候会执行呢 ———— 你自己把`waitHandle`函数中的`dtd.resolve()`改成`dtd.reject()`试一下就知道了。
93+
94+
- `dtd.resolve()` 表示革命已经成功,会触发`then`中第一个参数(函数)的执行,
95+
- `dtd.reject()` 表示革命失败了,会触发`then`中第二个参数(函数)执行
96+
97+
## 有什么问题?
98+
99+
总结一下一个`deferred`对象具有的函数属性,并分为两组:
100+
101+
- `dtd.resolve` `dtd.reject`
102+
- `dtd.then` `dtd.done` `dtd.fail`
103+
104+
我为何要分成两组 ———— 这两组函数,从设计到执行之后的效果是完全不一样的。第一组是主动触发用来改变状态(成功或者失败),第二组是状态变化之后才会触发的监听函数。
105+
106+
既然是完全不同的两组函数,就应该彻底的分开,否则很容易出现问题。例如,你在刚才执行代码的最后加上这么一行试试。
107+
108+
```javascript
109+
w.reject()
110+
```
111+
112+
那么如何解决这一个问题?请听下回分解!
113+
114+
## 求打赏
115+
116+
如果你看完了,感觉还不错,欢迎给我打赏 ———— 以激励我更多输出优质内容
117+
118+
![](http://images2015.cnblogs.com/blog/138012/201702/138012-20170228112237798-1507196643.png)
119+

part2-jquery/03-jquery-promise.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# jQuery promise
2+
3+
上一节通过一些代码演示,知道了 jquery 的`deferred`对象是解决了异步中`callback`函数的问题,但是
4+
5+
## 本节内容概述
6+
7+
- 返回`promise`
8+
- 返回`promise`的好处
9+
- promise 的概念
10+
11+
## 返回`promise`
12+
13+
我们对上一节的的代码做一点小小的改动,只改动了一行,下面注释。
14+
15+
```javascript
16+
function waitHandle() {
17+
var dtd = $.Deferred()
18+
var wait = function (dtd) {
19+
var task = function () {
20+
console.log('执行完成')
21+
dtd.resolve()
22+
}
23+
setTimeout(task, 2000)
24+
return dtd.promise() // 注意,这里返回的是 primise 而不是直接返回 deferred 对象
25+
}
26+
return wait(dtd)
27+
}
28+
29+
var w = waitHandle() // 经过上面的改动,w 接收的就是一个 promise 对象
30+
$.when(w)
31+
.then(function () {
32+
console.log('ok 1')
33+
})
34+
.then(function () {
35+
console.log('ok 2')
36+
})
37+
```
38+
39+
改动的一行在这里`return dtd.promise()`,之前是`return dtd``dtd`是一个`deferred`对象,而`dtd.promise`就是一个`promise`对象。
40+
41+
`promise`对象和`deferred`对象最重要的区别,记住了————**`promise`对象相比于`deferred`对象,缺少了`.resolve``.reject`这俩函数属性**。这么一来,可就完全不一样了。
42+
43+
上一节我们提到一个问题,就是在程序的最后一行加一句`w.reject()`会导致乱套,你现在再在最后一行加`w.reject()`试试 ———— 保证乱套不了 ———— 而是你的程序不能执行,直接报错。因为,`w``promise`对象,不具备`.reject`属性。
44+
45+
## 返回`promise`的好处
46+
47+
上一节提到`deferred`对象有两组属性函数,而且提到应该把这两组彻底分开。现在通过上面一行代码的改动,就分开了。
48+
49+
- `waitHandle`函数内部,使用`dtd.resolve()`来该表状态,做主动的修改操作
50+
- `waitHandle`最终返回`promise`对象,只能去被动监听变化(`then`函数),而不能去主动修改操作
51+
52+
一个“主动”一个“被动”,完全分开了。
53+
54+
## promise 的概念
55+
56+
jquery v1.5 版本发布时间距离现在(2017年初春)已经老早之前了,那会儿大家网页标配都是 jquery 。无论里面的`deferred``promise`这个概念和想法最早是哪位提出来的,但是最早展示给全世界开发者的是 jquery ,这算是`Promise`这一概念最先的提出者。
57+
58+
其实本次课程主要是给大家分析 ES6 的`Promise` `Generator``async-await`,但是为何要从 jquery 开始(大家现在用 jquery 越来越少)?就是要给大家展示一下这段历史的一些起点和发展的知识。有了这些基础,你再去接受最新的概念会非常容易,因为所有的东西都是从最初顺其自然发展进化而来的,我们要去用一个发展进化的眼光学习知识,而不是死记硬背。
59+
60+
## 求打赏
61+
62+
如果你看完了,感觉还不错,欢迎给我打赏 ———— 以激励我更多输出优质内容
63+
64+
![](http://images2015.cnblogs.com/blog/138012/201702/138012-20170228112237798-1507196643.png)

part2-jquery/test.html

Lines changed: 74 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,81 @@
1010
<script type="text/javascript" src="//cdn.bootcss.com/jquery/2.2.3/jquery.js"></script>
1111
<script type="text/javascript">
1212

13-
var ajax = $.ajax({
14-
url: '/data/data1.json',
15-
success: function () {
16-
console.log('success')
17-
},
18-
error: function () {
19-
console.log('error')
13+
// -------- 打印 $.ajax 返回值 -------
14+
function fn1() {
15+
var ajax = $.ajax({
16+
url: '/data/data1.json',
17+
success: function () {
18+
console.log('success')
19+
},
20+
error: function () {
21+
console.log('error')
22+
}
23+
})
24+
console.log(ajax)
25+
}
26+
// fn1()
27+
28+
29+
// -------- 使用 $.Deferred() --------
30+
function fn2() {
31+
function waitHandle() {
32+
var dtd = $.Deferred() // 创建一个 deferred 对象
33+
var wait = function (dtd) { // 要求传入一个 deferred 对象
34+
var task = function () {
35+
console.log('执行完成')
36+
dtd.resolve() // 改变 deferred 对象的执行状态
37+
}
38+
setTimeout(task, 2000)
39+
return dtd // 要求返回 deferred 对象
40+
}
41+
return wait(dtd)
42+
}
43+
var w = waitHandle()
44+
w.then(function () {
45+
console.log('ok 1')
46+
}, function () {
47+
console.log('err 1')
48+
}).then(function () {
49+
console.log('ok 2')
50+
}, function () {
51+
console.log('err 2')
52+
})
53+
54+
// deferred 对象直接暴露出来,很容易出现问题,如下代码
55+
// w.reject()
56+
}
57+
// fn2()
58+
59+
// ------- 优化 返回 promise ------
60+
function fn3() {
61+
62+
function waitHandle() {
63+
var dtd = $.Deferred()
64+
var wait = function (dtd) {
65+
var task = function () {
66+
console.log('执行完成')
67+
dtd.resolve()
68+
}
69+
setTimeout(task, 2000)
70+
return dtd.promise() // 注意,这里返回的是 primise 而不是直接返回 deferred 对象
71+
}
72+
return wait(dtd)
2073
}
21-
})
22-
console.log(ajax)
74+
75+
var w = waitHandle()
76+
$.when(w)
77+
.then(function () {
78+
console.log('ok 1')
79+
})
80+
.then(function () {
81+
console.log('ok 2')
82+
})
83+
84+
// w.resolve() // 如果这里再想执行 resolve 就会直接报错,这样就避免了以上提出的问题
85+
86+
}
87+
fn3()
2388

2489
</script>
2590
</body>

0 commit comments

Comments
 (0)