同步与异步
同步:阻塞式,一定要等上一段代码出来之后,才能继续执行
异步:非阻塞式,什么时候执行完了,会通过事件触发来告诉我们(事件是其中一种方式)
FileReader(文件读取器)、setTimeout、setInterval
ajax
(异步JavaScript 和 XML【可扩展标记语言】)
- url:访问的地址
- method:请求方式 如:GET、POST
- data:传递给后端的数据(POST才用)
- callback:回调函数 ()
function ajax(url,method,data,callback){
// 创建XMLHttpRequest对象:xml
let xhr = new XMLHttpRequest()
// 打开通道
xhr.open(method,url)
// 发送请求
xhr.send(data)
// 通过事件来获取响应结果
xhr.onreadystatechange=function(){
// readstate=4说明请求已经完成
if(this.readstate == 4){
if(status == 200){
callback(JSON.parse(this.responseText))
}else{
console.log(this.statusText)
}
}
}
}
ajax(url.‘GET’,null,function(result){
resout.forEach(item => {
let
})
})
/**
* url 访问地址
* method 请求方式:GET、POST
* data 传递给后端的数据(POST才用)
* callback 回调函数(将异步的结果放进去)
*/
function ajax(url,method,data,callback){
//1.创建XMLHttpRequest对象:xhr
let xhr = new XMLHttpRequest();
//2.打开通道
xhr.open(method,url);
if(method.toUpperCase()=='POST'){
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
}
//3.发送请求
xhr.send(data);
//4.通过事件来获取响应结果
xhr.onreadystatechange=function(){
//5.readyState=4说明整个请求已经完成了
if(this.readyState==4){
//6.获取HTTP状态码,如果是200则成功
if(this.status==200){
let res = JSON.parse(this.response)
if(res.errcode){
alert(res.errmsg)
return;
}
//将结果传给回调函数
callback(res);
}else{
//7.如果状态码不是200,我们就打印状态文本,例如:404 文本就是 Not Found
console.log(this.statusText)
}
}
}
}
在onreadystatechange事件中,通过ajax的readyState 监听服务器的处理进度:
0:初始化,XMLHttpRequest对象还没有完成初始化
1:载入, XMLHttpRequest对象开始发送请求 —open
2:载入完成,XMLHttpRequest对象的请求发送完成—send
3:解析,XMLHttpRequest对象开始读取服务器的响应
4:完成,XMLHttpRequest对象读取服务器响应结束
Content-Type:
- 纯文本 text/plain
- JSON application/json
- form表单 application/x-www-form-urlencoded
- 文件上传 multiple-form
回调地狱
多层回调函数嵌套,使得程序变得难以维护,可读性差
setTimeout(function() {
console.log('Yay!');
setTimeout(function() {
console.log('Yahoo!');
setTimeout(function(){
//回调地狱
},1000)
}, 1000)
}, 1000);
Promise(承诺)
ES6推出了Promise语法结构来解决回调地狱问题。
这也就表达了将来会执行的操作,代表异步操作。
三种状态:
pending(进行中)、fulfilled(已成功)和rejected(已失败)
状态改变的过程:
pending->fulfilled
pending->rejected
一旦变成了成功或失败状态,状态就不会再变化。
创建Promise实例:
const promise = new Promise((resolve, reject) => {
// do something here ...
if (success) {
resolve(value); // fulfilled
} else {
reject(error); // rejected
}
});
//通过then方法,分别指定resolved状态和rejected状态的回调函数
promise.then(function(value) {
// success
}, function(error) {
// failure
});
用Promise改造Ajax:
/**
* url 访问地址
* method 请求方式:GET、POST
* data 传递给后端的数据(POST才用)
*/
function ajax(url,method,data){
return new Promise((resolve,reject)=>{
//1.创建XMLHttpRequest对象:xhr
let xhr = new XMLHttpRequest();
//2.打开通道
xhr.open(method,url);
if(method.toUpperCase()=='POST'){
xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
}
//3.发送请求
xhr.send(data);
//4.通过事件来获取响应结果
xhr.onreadystatechange=function(){
//5.readyState=4说明整个请求已经完成了
if(this.readyState==4){
//6.获取HTTP状态码,如果是200则成功
if(this.status==200){
let res = JSON.parse(this.response)
if(res.errcode){
alert(res.errmsg)
return;
}
//将结果传给回调函数
resolve(res);
}else{
//7.如果状态码不是200,我们就打印状态文本,例如:404 文本就是 Not Found
reject(this.statusText)
}
}
}
})
}
let url = 'http://yapi.smart-xwork.cn/mock/91220/user/list'
ajax(url,"GET",null).then(result=>{
if(result instanceof Array){
//遍历结果
result.forEach(item=>{
//创建LI标签
let li = document.createElement("li");
li.innerHTML = item.name +":"+ item.sex;
//将LI追加到UL中
document.getElementById("parent").appendChild(li);
})
}
},error=>{
console.log("失败:" +error);
})
Promise中的异常捕获:
方式一:
ajax(‘GET’,’api/seller.do’,’username=jackie’).then((data)=>{
console.log(data);//成功获得结果
},(err)=>{
console.log(err);//获取错误信息
}
方式二:
ajax(‘GET’,’api/seller.do’,’username=jackie’).then((data)=>{
console.log(data);//成功获得结果
}).catch(err=>{
console.log(err);//获取错误信息
})
Promise.all
<script>
function p1() {
return new Promise((resolve, reject) => {
resolve("sccess");
});
}
function p2() {
return new Promise((resolve, reject) => {
reject("over");
// resolve("sccess");
});
}
function p3() {
return new Promise((resolve, reject) => {
resolve("sccess");
});
}
Promise.all([p1(), p2(), p3()]).then(
(res) => {
console.log(res);
},
(err) => {
console.log(err);
}
);
Promise.all([p1(), p2(), p3()])
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});
</script>
Promise.allSettled
同时启动多个,不论成功还是失败都会返回全部的结果。
- Promise.allSettled([p1(),p2(),p3()])
<script>
function p1() {
return new Promise((resolve, reject) => {
resolve("sccess");
});
}
function p2() {
return new Promise((resolve, reject) => {
reject("over");
// resolve("sccess");
});
}
function p3() {
return new Promise((resolve, reject) => {
resolve("sccess");
});
}
Promise.allSettled([p1(), p2(), p3()]).then((arr) => {
console.log(arr);
});
</script>
(3) [{…}, {…}, {…}]
0: {status: 'fulfilled', value: 'sccess'}
1: {status: 'rejected', reason: 'over'}
2: {status: 'fulfilled', value: 'sccess'}
length: 3
[[Prototype]]: Array(0)
Promise.race()
race:比赛
多个promise比赛,看谁先执行到最终状态。率先改变
- promise.race[p1,p2,p3].then(res=>{console.log(res)})
<script>
Promise.race([p1(), p2(), p3()])
.then((arr) => {
console.log(arr);
})
.catch((arr) => {
console.log(arr);
});
</script>
async
- 给函数前加async关键字,函数的返回值就会变成一个Promise对象
- 如果我们手动在函数里面return了一个值,则这个值就是Promise对象里面的value,通过then可以取出
<script>
async function play() {
return 123;
}
console.log(play()); // promise
play().then((arr) => console.log(arr));
</script>
async - await
- async_await:能让异步代码看起来像是同步代码
<script>
async function show(){
return 123;
}
async function play(){
var res = await show()
console.log(res);
}
play()
</script>
<body>
<script>
function ajax(url, method, data) {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
xhr.open(method,url);
xhr.send(data);
xhr.onreadystatechange = function () {
if (this.readyState == 4) {
if (this.status == 200) {
let res = JSON.parse(this.response);
resolve(res);
} else {
reject(this.statusText);
}
}
};
});
}
async function play() {
try {
let url =
"http://yapi.smart-xwork.cn/mock/94700/user/information/user/get";
let res = await ajax(url, "GET", null);
console.log(res);
} catch (error) {
console.log(error);
}
}
play();
</script>