实际开发中,我们享受着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