善用ajax异步请求和deferred对象

177 阅读1分钟

场景:

当我们需要得到两个接口的结果后,才执行下一步逻辑时,举个栗子:

假如我们去相亲,需要知道对方的长相和家庭条件后,才进行下一步交往。

同步等待的做法:

var looks = 0 // 长相0分
var money = 0 // 条件0分
// 线下获取长相
getLooks: function() {
	$.ajax({
		url: 'xxx',
		async: false, // 同步执行
		success: function(res) {
			// 长得可以,100分
			looks = 100
		}
	})
}

// 线下询问家庭条件
getMoney: function() {
	$.ajax({
		url: 'xxx',
		async: false, // 同步执行
		success: function(res) {
			// 条件可以,100分
			money = 100
		}
	})
}

getLooks()
getMoney()

// 不过不设置同步 async: false,此处判断只会是false
if (looks && money) {
	// 长相,家庭条件都可以,进一步交往
	contact()
} else {
	// 不满意,继续逛街
	shopping()
}

这种做法需要先见面判断,然后等待结果,才能进行下一步操作,同步的方式也阻碍了我逛街的进程。

异步等待的做法:

// 微信拍照获取长相
getLooks: function() {
	$.ajax({
		url: 'xxx',
		success: function(res) {
			// 长得可以,问他家庭条件
			getMoney()
		}
	})
}

// 微信询问家庭条件
getMoney: function() {
	$.ajax({
		url: 'xxx',
		success: function(res) {
			// 条件可以,进一步交往
			contact()
		}
	})
}

getLooks()
shopping()

这种做法可以判断与逛街同时进行,不会阻碍逛街的进程,"一问一答"的方式,但是一旦判断条件多了,比如还需判断家庭情况,文化水平等等,要等待上一个问题的答案,会出现层层嵌套的问题。

异步优雅的做法:

// 获取长相
getLooks: function() {
	var def = $.Deferred() // 延迟等待调用
	$.ajax({
		url: 'xxx',
		success: function(res) {
			def.resolve(res)
		}
	})
}

// 家庭条件
getMoney: function() {
	var def = $.Deferred() // 延迟等待调用
	$.ajax({
		url: 'xxx',
		success: function(res) {
			def.resolve(res)
		}
	})
}

// 一次性把条件问完,只需等待所有结果一起返回,直接做判断
$.when(getLooks(), getMoney()).then(function(looks, money){
	// 各方面条件可以,进一步交往
	contact()
}, function(looks,money){
	console.log('不合适,继续逛街')
})

shopping()

这种做法不会阻碍逛街的进程,所有判断条件也可以一次性执行,不需要等待一个个执行,只需等待所有结果都返回,便可做出判断。

小结:

1、接口请求避免使用同步方式,会阻碍进程,出现页面假死状态,交互非常不友好。

2、当需要多个接口结果时,可以使用.Deferred()配合.Deferred()配合.when()的方式。

3、此外,Deferred还有always()方法,用于:无论接口是否成功,都执行下一步操作。

参考文档:

阮一峰 -《jQuery的deferred对象详解》

www.ruanyifeng.com/blog/2011/0…