问题背景
同步
是指一件事一件事的执行,只有前一个任务执行完毕,才能执行后一个任务。
异步(async)
是相对于同步(sync)
而言的,由于JavaScript是单线程运行的,为了避免阻塞带来的糟糕体验,异步操作成了必不可少的一种编程模式,js实现异步操作的方式有很多,包括回调函数、时间监听、发布/订阅模式、定时函数,包括ES6及以后的promise,Generator函数及各种语法糖。
这里拿ajax举例子,有些时候处于某些特殊情况,我们需要整个ajax(包括其成功或者失败之后的回调函数)执行完毕才进行后续操作。
var responseData;
$.getJSON({
url: '../src/wind-gbr.json',
success: function(response){
responseData = response;
console.log("1st",responseData[0].header);
}
});
console.log("2nd",responseData[0].header);
上面这段代码中,处于某种目的,第二句输出不想放在success回调函数中而需要放在外面,我们都知道这样运行肯定会抛出一个错误提示responseData不存在,那么我们就需要一些变通的操作,来完成我们的目标。
异步编程同步化
1. 最简单的做法:直接修改ajax中的async属性为true,这将使得其变为同步请求而锁住浏览器,其它操作必须等待请求完成才可以执行。
$.getJSON({
url: '../src/wind-gbr.json',
async: false,
success: function(response){
responseData = response;
console.log("1st",responseData[0].header);
}
});
console.log("2nd",responseData[0].header);
2. promise模式:
var promise = new Promise(function(resolve, reject) {
$.getJSON({
url: '../src/wind-gbr.json',
async: false,
success: function(response){
responseData = response;
console.log("1st",responseData[0].header);
resolve();
}
});
});
promise.then(function(value) {
console.log("2nd",responseData[0].header);
});
3. Generator函数法:(这里为了直观写了个按钮启动下一部操作,当然可以写一个自动完成的函数)
var myfun=(function* () {
while(true){
$.getJSON({
url: '../src/wind-gbr.json',
success: function(response){
responseData = response;
console.log("1st",responseData[0].header);
}
});
yield;
console.log("2nd",responseData[0].header);
yield;
}
})();
var btn=$('button').click(()=> {
myfun.next();
});
4. async和await:
var myfun=(async function () {
await $.getJSON({
url: '../src/wind-gbr.json',
success: function(response){
responseData = response;
// console.log("1st",responseData[0].header);
}
});
await console.log("2nd",responseData[0].header);
})();
5. async结合promise:(因为async函数的返回值是一个promise对象)
var myfun=(async function () {
return $.getJSON({
url: '../src/wind-gbr.json',
success: function(response){
responseData = response;
console.log("1st",responseData[0].header);
}
});
})();
console.log(myfun);
myfun.then(()=>{console.log("2nd",responseData[0].header);});