为什么会出现异步
js是一门为浏览器而诞生的语言,发展到现在,js已经不仅仅只在浏览器上运行了,服务端也可以运行js,像node。而js最初设计是单线程,也就是说会一行一行的执行,下面需要等待上面代码执行完毕,也就是说在特定的时刻只能做特定的事情,阻塞其他代码的执行。
常用的异步例如网络请求、读取文件等。
异步解决方案
了解javascript为什么会出现异步,那么我们该怎么去解决异步呢?如何书写日常工作中的工程代码呢?javascript的演变中出现了如下几种解决方案。
callback
一般在网络请求中我们并不知道服务端啥时候返回结果,在这个等待的过程中,我们不能让页面一直卡顿或是不能操作的状态,这样会给用户很不好的体验感觉,我们又需要在服务端返回结果的时候来进行相应的操作或是数据更新。于是回调函数就成为异步的第一个解决方案,如下:
$.ajax({
"url": "",
success: function(data){
//函数返回成功需要进行的操作或数据更新
},
error: function(err){
//函数返回失败需要进行的操作或提示
}
})
这是在jq中我们非常熟悉的一个操作,当我们去请求服务端时,不管成功或失败,服务端都会返回一个结果,success和error函数就是一个callback函数,不管成功或是失败,我们都能进行相应的操作或是提示,在网络请求的过程中,并不影响用户对别的操作(除非不想让用户操作,必须要等待这个操作完成),当服务端返回数据时,我们可以通过callback接收到,这个时候我们再进行相应的操作。
Promise
在callback中,如果当前网络请求需要依赖前一个网络请求,我们就有可能掉进回调地狱,
如图:
于是promise的出现为我们解决了这个问题。promise是在ES6中被统一规范,由浏览器直接支持,promise为一诺千金的意思,意思是在将来不管这个状态成功或是失败,都将返回一个结果。
promise有三种状态:
等待中 pending;
已完成 fulfilled;
已拒绝 reject;
let test = new promise(resolve,reject){
if(success){
resolve();
}else{
reject();
}
}
test()
.then(res => {
//成功时返回函数
})
.catch(err => {
//失败时返回函数
})
Generator
我们希望以同步方式写异步代码,可以使逻辑清晰,代码简洁,为了实现这种目的,我们又演进出generator方案,
function * add(x){
yield x + 50;
yield x + 100;
return x + 150;
}
let test = add(5);
test.next(); //done: true , value: 55
test.next(); //done: true , value: 105
test.next(); //done: true , value: 155
如上,genertor与普通函数区别不大,function后面加了一个*,
首先定义了一个test = add(5),函数没有执行,只是生成了一个genertor对象,函数属于暂停状态,只有当执行.next()时,才会激活暂停状态,开始执行内部代码,遇到第一个yield才会返回执行结果,并记住上下文,暂停,交出控制权,再次执行,找到第二个yield,并重复上述步骤
function* Fn(){
var result = yield ajax(url);
var result1 = yield ajax(url1);
}
let F = Fn();
var result = F.next();
result.value
.then(res => {
F.next();
})
.catch(err => {
})
如上 封装一个ajax异步,定义一个genertor对象,执行请求交出控制权,根据返回结果执行第二个ajax请求
asnyc/await
ES7的asnyc/await号称是异步的终极解决方案,让我们以同步的方式来书写异步代码,这样看起来更简洁,逻辑更清晰。
比如微信小程序烦人的异步:
const Login = data => {
return new Promise( (resolve, reject) => {
wx.login({
success: res => {
resolve(res);
},
fail: err => {
reject(err);
}
})
})
}
const getUserInfos = data => {
return new Promise((resolve,reject){
wx.getUserInfo({
success: res => {
resolve(res);
},
fail: err => {
reject(err);
}
})
})
}
const sendCode = data = > {
return new Promise((resolve,reject){
wx.request({
url: '',
success: res=> {
resolve(res);
},
fail: err => {
reject(err);
}
})
})
}
以上就是封装好的微信登录过程中的获取code userInfo 和发送ajax请求的几个函数,
然后
asycn function getLogin(){
try {
let result_login = await Login();
let result_userInfo = await getUserInfos();
result_userInfo['code'] = result_login['code'];
let result_sendCode = await sendCode(result_userInfo );
return result_sendCode;
}catch(err){
console.log(err);
}
}
getLogin()
.then(res => {
})
.catch(err => {
}
async与genertor的写法类似,具备更好的语义,并且返回的是promise
作者:lzksdxh
链接:https://juejin.im/post/5af8f706f265da0b8f62a7d1
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。