异步,同步
- 同步异步不是指时间的长短,而是能否直接拿到结果
- js执行一行代码,这一行没执行完不拿到结果我是不会走的,这就是同步
- 同样js执行一行代码,这一行没执行完我先等等再来让你先执行,我一会来拿结果,这就是异步
- 例子: 以AJAX为例
AJAX有流程,从创建实例开始 ==> open() ==> 监听是否成功 ==> send()
- 同步:如果AJAX是同步,那么这四个代码下来到send()函数调用完,等AJAX就执行完了,我们就可以得到结果即response
- 如以下代码,send()函数调用完,我们必须等到拿到结果,才会执行下一步,所以console.log(request.response);是有效的
getCss.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/public/style.css",false);
request.onreadystatechange = () => {
if (request.readyState === 4) {
const style = document.createElement("style");
style.innerHTML = request.response;
document.querySelector("head").appendChild(style);
}
};
request.send();
console.log(request.response);
};
- 异步:send()函数调用完,并不能拿到结果
- 以下代码console.log是可以直接拿到response的
getCss.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/public/style.css");
request.onreadystatechange = () => {
if (request.readyState === 4) {
const style = document.createElement("style");
style.innerHTML = request.response;
document.querySelector("head").appendChild(style);
}
};
request.send();
console.log(request.response);
};
异步种类
异步有两种一种是代码执行时间太长,你得等一会,另一种是代码现在条件不够不能执行,AJAX就是前者,onreadystatechange就是后者
- AJAX就是前者,比方有两个按钮,当你监听点击按钮事件,你按第一个请求CSS,第二个请求HTML,你点击第一个时,不用等到得到结果,你就可以点击第二个,如下图第一个是异步,第二个是同步


- AJAX请求只会刷新局部(诞生目的)
- onreadystatechange和settimeout就是条件不够异步的,我现在条件不够不能调用等会通知你调用吧
回调,轮询
- 通常异步通常和回调或者轮询结合
- 异步就是一会通知你调用/拿结果
- 如果浏览器自己收到通知就去调用了,那么这个函数就叫回调,
onreadystatechange和settimeout的值/参数就是回调 - 写给别人用的函数就是回调
- 如果你隔一会儿看看,那么就是轮询
异步,回调
- 通常异步通常和回调或者轮询结合
- 拿下面代码为例,就是异步回调,onreadystatechange值就是回调
getCss.onclick = () => {
const request = new XMLHttpRequest();
request.open("GET", "/public/style.css");
request.onreadystatechange = () => {
if (request.readyState === 4) {
const style = document.createElement("style");
style.innerHTML = request.response;
document.querySelector("head").appendChild(style);
}
};
request.send();
console.log(request.response);
};
- onreadystatechange是异步,它的值是回调
- 异步:我按下这个按钮,你先执行着,我去按下一个按钮去了
- 回调:你执行完,拿到结果,记得回头调用一下那个函数
异步函数
- setTimeout,XHR,AddEventListen就是异步
- 看文档
回调函数
回调函数简写
const array = ['1','2','3'].map(parseInt)
这样简写的前提就是参数一致,等价于
const array = ['1','2','3'].map((item,i,arr) =>{
return parseInt(item,i,arr)
})
显然是不对的
const array = ['1','2','3'].map((item,i,arr) =>{
return parseInt(item)
})
map函数:在map里面调用parseInt
调用下面函数,因为parseInt定义的时候也是类似下面函数定义的,虽然map里面看不出parseInt参数,但它实际上是有参数的,简写的原理就讲清了
(item,i,arr) =>{
return parseInt(item,i,arr)
}
回调总结
const array = ['1','2','3'].map(parseInt)
parseInt(a,b)
虽然map里的parseInt看起来没有参数,但它在定义的时候是有参数(a,
b)的,它的逻辑和普通写法是一样的,它定义时的参数(a,b)被赋值,然后调用,这不就是普普通通的传值吗,所以可以这样简写
异步两个结果
假设异步,我们让它自己去执行/自己选时间去执行,那么就有是否执行成功两个结果
- 回调接受两个参数
- 两个回调
fs.readFile('./1.txt', (error, data)=>{
if(error){ console.log('失败');
return
}
console. log(data. toString()) //成功
})
ajax('get ',/1. json',data=>{},error=>{})
AJAX封装
以上方法都不够规范,没有统一规定,代码可读性太差
const ajax = (method, url, options) => {
const request = new XMLHttpRequest();
request.open(method, url);
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status < 400) {
options.sucess.call(null, request.response);
} else {
options.fail.call(null, request, request.status);
}
}
};
request.send();
};
首先封装一下AJAX(options是一个对象里面有两个方法)
promise改造
封装之后调用:ajax("GET","/xxx",{success:()=>{},{fail:()=>{}})
改造后:ajax("GET","/xxx").then((response)=>{},(request)=>{},)按照jquery的思想返回一个API,里面有一个then方法,接受两个参数,默认第一个是成功,把函数嵌套变成了.then().then()
const ajax = (method, url, options) => {
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open(method, url);
request.onreadystatechange = () => {
if (request.readyState === 4) {
if (request.status < 400) {
resolve.call(null, request.response);
} else {
reject.call(null, request, request.status);
}
}
};
request.send();
});
};
只是简单封装了一下GET,而且没有设置请求头,重点在于理解返回API的思想,Promise里面有then()
总结
- 异步任务不能拿到结果(两个原因)
- 于是我们传一个回调给异步任务
- 异步任务完成时调用回调
- 调用的时候把结果作为参数,我们对结果进行操作
- promise是为了异步的诞生的,异步拿不到的结果给promise就好了
- promise是异步和回调结合