记录jQuery同步Ajax带来的UI线程阻塞问题及解决办法

实际开发中,我们享受着Ajax异步请求带来的便利,使我们开发更加快速,但是有时也需要一些同步请求来满足我们的开发需求。将Ajax中async属性设置为false,即可让Ajax请求变为同步请求,然而,Ajax中同步操作是一个巨坑。

由于开发JavaScript是单线程的,当我们使用Ajax同步请求时,线程将停在等待请求response的地方,直到收到response,线程才继续执行。这导致了程序无法执行其他js命令, 带来了线程阻塞问题,具体体现方式是UI界面卡住。

这里的ajax不能用异步的,否则函数返回时,result还未赋值,会出错。所以加了async:false。但是带来的另一个问题就是线程阻塞。如下:

function getData(){
        var result;
        $.ajax({
            url : 'p.php',
            async : false,
            success: function(data){
                result = data;
            }
        });

    return result;
}

找了一下资料,发现几种方法都可以完美解决问题,具体代码如下:

Deferred:


function getData(){
    var defer = $.Deferred();
    $.ajax({
        url : 'p.php',
        //async : false,
        success: function(data){
            defer.resolve(data)
        }
    });
    return defer.promise();
}    

// getData()返回Promise对象
$.when(getData()).done(function(data){
    alert(data);
});

Promise:

getData() {
	return new Promise((resolve, reject) => {
		$.ajax({
			url : 'p.php',
			//async : false,
			success: function(data){
				defer.resolve(data)
			},
			error: function(result) {
				reject("throw error")
			}
		})
	})
}

// 调用
getData().then(function(data){
    console.log(data)
}).catch(function(err){
    console.log(err)
})

在ES6中,还可以使用Generator来创建异步编程

function* getData() {
	let result;
	$.ajax({
		url : 'p.php',
		success: function(data){
			result = data;
		}
	});
	yield;
	return result
}

var gd = getData()
console.log(gd.next()) // {value: undefined, done: false}
console.log(gd.next()) // {value: data, done: false}

在ES8中,引入了async函数,使得异步操作变得更加方便。简单说来,它就是Generator函数的语法糖。

async用于定义一个异步函数,该函数返回一个Promise。
如果async函数返回的是一个同步的值,这个值将被包装成一个理解resolve的Promise,等同于return Promise.resolve(value)
await用于一个异步操作之前,表示要“等待”这个异步操作的返回值。await也可以用于一个同步的值。

async await:

let getData = async () => {
	let result;
	await $.ajax({
			url : 'p.php',
			success: function(data){
				result = data;
			}
		});
	return result
}

// getData()返回Promise
getData().then(data => {
	console.log(data)
})

 

总结:

几种方法返回几乎都是Promise对象,Generator除外,由此可以看出,几种方法采用都是Promise异步调用原理,而Generator生成器中用的yeild关键字,类似于协程,yield个人认为其实是为了实现协程而出现的。

Generator是一个状态机,它封装了多个内部状态,执行它将生成一个遍历器对象,而async函数是Generator函数的语法糖,await返回一个Promise对象,如果不是,会被转换成一个立即执行的Promise对象,await将等待当前行执行完成才会继续之后的内容。

 

ps:异步编程的几种方式

1. 回调函数

2. 事件监听

3. 发布/订阅

4. Promise

5. Generator、Async/Await

参考资料 http://www.jiangweishan.com/article/JSbiancheng20180428.html

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值