在实际开发中常常遇到这样的问题:B函数中需要用到的变量或者参数,只有等A函数执行完毕了才能获取到。比如A函数中有一个ajax请求,而B函数中所需要的position
变量需要在A函数中ajax请求完成才能得到它的准确值。
function A() {
$.ajax({
url: '/api/test',
type: 'POST',
data: {...},
success: function(res) {
position = res.position;
}
})
}
function B() {
$('.test').text(position);
}
JavaScript的异步模式让B函数不会等待A函数计算出了position
的值才会执行,它会不等待A函数的结果而直接开始执行,这样就会造成position
无法正确赋值。为了解决这个问题,我们很容易想到使用回调函数,这也是最常用的方法之一
function A(callback) {
$.ajax({
url: '/api/test',
type: 'POST',
data: {...},
success: function(res) {
position = res.position;
callback && callback();
}
})
}
function B() {
$('.test').text(position);
}
A函数有了回调之后,就可以将B函数当做回调函数传递给A
A(B);
可是如果这个时候,还有一个C函数,依赖于B的执行结果呢,后面甚至有可能出现一个D函数,依赖于C的结果!又如我们常用的ajax,成功了会有一个回调函数,失败了还有一个回调函数,面对这样复杂的情况,我们应该怎么样处理?虽然使用回调函数依然能够搞定这些烦人的难题,但是很显然这并不是一个好的解决办法。
jquery中的Deferred
对象很好的解决了这个问题。在了解Deferred
之前,我们可能需要了解一个JavaScript中的promise
模式。当我们使用回调来解决实际中的问题时,很容易不知不觉中出现代码金字塔
step1(function() {
step2(function() {
step3(function() {
step4(function() {
step5();
})
})
})
})
假如这个时候有一个js库实现了promise模式,那么我们的代码就会变得清晰可读,并且每一步都会等待上一步执行完毕了才会执行。
new Promise().when(promiseStep1)
.then(promiseStep2)
.then(promiseStep3)
.then(promiseStep4)
.then(promiseStep5);
每一个promise对象都可以设置三种状态:
pending [进行中]
resolve [已经正确执行]
reject [执行失败]
关于promise,还有更多需要了解的地方,我这里只是抛砖引玉。回到jQuery的Deferred对象来。jquery的Deferred对象就是对promise模式的一个很好的实现案例。我们通过一个简单的例子来看看Deferred对象应该如何使用。
函数first
是一个耗时两秒的操作,而函数second
是一个简单的函数,但是他需要在first
执行完毕之后才执行。
function first() {
setTimeout(function() {
console.log('first');
}, 2000);
}
function second() {
console.log('second');
}
为了达到second在first之后执行,使用Deferred对first函数做一个简单的处理即可
function first() {
// 1
var defer = $.Deferred();
setTimeout(function() {
console.log('first');
// 2
defer.resolve();
}, 2000);
// 3
return defer.promise();
}
1、在函数中声明一个Deferred对象,这样在外部就无法修改函数内部的执行状态
2、函数执行完毕,设置执行状态,如果成功执行,defer.resolve()
,如果执行失败,则设置为defer.reject()
3、在函数的最后,必须将deferred对象返回出去,否则外部无法得到函数的执行结果
在做了这样的处理之后,我们就可以满足要求的正常使用了
$.when(first())
.done(second());
jquery中,ajax方法就是使用promise模式完成的,我们可以看看常规写法和Deferred对象写法的不同。
// 常规写法
$.ajax({
url: '/api/test',
type: 'POST',
data: {...},
success: function(res) {
// dosomething
},
fail: function(res) {
// dosomething
},
complete: function() {
// dosomething
}
})
// 新的写法
$.ajax({
url: '/api/test',
type: 'POST',
...
})
.done(function(res) {
// success and do something
})
.fail(function(res) {
// fail and do something
})
.always(function() {})
这个知识点差不多就总结完毕了。Promise模式与Deferred对象都还有更多值得了解知识点与用法,这是一个非常值得掌握的神兵利器,建议大家搜索更多的文章来学习它。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。