学习内容
- 异步问题
- promise基本语法
- promise应用
- async_awite
- 面试版-ajax
异步问题
//1. 如何让异步程序按顺序执行?
//2. 具有依赖调用的问题?
//需求:3秒后输出1,再过2秒输出2,再过1秒输出3,再过半秒输出4
setTimeout(() => {
alert(1);
setTimeout(() => {
alert(2);
setTimeout(() => {
alert(3);
setTimeout(() => {
alert(4);
}, 500);
}, 1000);
}, 2000);
}, 3000);
//
<script src="js/index.js" type="module"></script>
=> //导入模块
import {ajax} from '../utils/utils.js';
// let result = await ajax({ url: '/test/first'});
// console.log(result);
ajax({url: '/test/first'})
.then((data) => {
console.log(data);
})
promise基本语法
//什么是Promise?
//ES6提出的异步编程解决方案;
//承诺的意思,是一个专门用来解决异步 回调地狱 的问题;
//回调地狱,其实就是回调函数嵌套过多导致的。
//当代码成为这个结构以后,已经没有维护的可能了;
//所以我们要把代码写的更加的艺术一些。
//检测机构
//new Promise((resolve,reject) => {
// //resolve: 成功 reject:失败
// if(异步程序){
// resolve([参数])
// }else{
// reject([参数]);
// }
//})
//原型方法
//then(([参数]) => {}) : 如果promise对象返回resolve时,可以调用then进行后续的处理
//catch(([参数] => {})): 如果promise对象返回reject时,可以调用catch方法进行后续的处理
// 3秒后输出1,再过2秒输出2
new Promise((resolve,reject) =>{
setTimeout(() => {
//成功了
resolve(1);
}, 3000);
})
.then((data) => {
alert(data); //1
setTimeout(() => {
alert(2);
}, 2000);
})
.catch((err) => {
alert('失败');
})
promise应用
//Promise的静态方法
//Promise.all() 将调用所有的promse对象,全部返回resolve时,该对象才返回resolve。如果有一个promise返回reject时,该对象返回reject。
//面试题: promise中有三种状态,哪三种状态?
//1. pending: 进行中状态;
//2. resolved / fulfilled: 成功状态;
//3. rejected: 失败状态。
/*
这个时候,我们的代码已经改观了很多了;
基本已经可以维护了;
但是对于一个程序员来说,这个样子是不够的;
我们还需要更加的简化代码;
所以我们就需要用到一个 es7 的语法了;
叫做 async / await。
*/
//
//需求:3秒后输出1,再过2秒输出2,再过1秒输出3,再过半秒输出4
//创建promise对象
new Promise((resolve,reject) => {
setTimeout(() => {
resolve(1);
}, 3000);
})
.then((data) => {
alert(data); //1
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(2);
}, 2000);
})
})
.then((data) => {
alert(data); //2
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(3);
}, 1000);
})
})
.then((data) => {
alert(data); //3
setTimeout(() => {
alert(4);
}, 500);
})
.catch(() => {
console.log('失败');
})
//
//封装一个promise的函数
function loadImg(src){
//创建一个promise对象
return new Promise((resolve,reject) => {
//创建一个img标签
let img = new Image(); //document.createElement('img')
//设置img的src属性
img.src = src; //后面的src是形参,接收回来的是一个图片地址
//给图片注册加载事件
img.onload = function(){
//调用resolve
resolve(this); //this: img对象
}
//给图片注册失败事件
img.onerror = function(){
reject(new Error('图片加载失败'));
}
})
}
//准备一个数组,存放所有的图片
let arr_img = ['./img/1.webp','./img/2.webp','./img/3.webp'];
//调用加载函数
let o_p = loadImg(arr_img[1]);
o_p.then((img) => { //走到这一步,说明浏览器已经加载图片成功了
document.body.appendChild(img);
})
o_p.catch((err) => {
console.log(err);
})
//
//封装一个加载图片的函数
function loadImg(url){
//返回一个promise对象
return new Promise((resolve,reject) => {
//创建一个img对象
let img = new Image();
//设置src属性
img.src = url;
//注册成功的事件
img.onload = function(){
resolve(img);
}
//注册失败的事件
img.onerror = function(){
reject(new Error('图片加载失败'));
}
})
}
//准备一个数组,存放图片
let arr_img = ['./img/1.webp','./img/2.webp','./img/3.webp'];
//调用加载图片的函数
//all : 所有、全部
// let o_p = Promise.all([loadImg(arr_img[0]),loadImg(arr_img[11]),loadImg(arr_img[2])]);
let o_p = Promise.race([loadImg(arr_img[0]),loadImg(arr_img[1]),loadImg(arr_img[2])]);
o_p.then((img) => {
document.body.appendChild(img);
})
// o_p.then((imgs) => {
// let body = document.body;
// imgs.forEach((item) => {
// body.appendChild(item);
// })
// })
// o_p.catch((err) => {
// console.log(err);
// });
async_awite
//ASYNC / AWAIT
async / await 是一个 es7 的语法;
这个语法是 回调地狱的终极解决方案。
语法:
async function fn() {
const res = await promise对象
}
//async 和 await 关键字
//注意: 需要配合的必须是 Promise 对象;
//注意: Promise 语法的调用方案;
//意义: 可以把异步代码写的看起来像同步代码。
//async 关键字的用法
//直接书写在函数的前面,表示该函数是一个异步函数;
//意义: 表示在该函数内可以使用 await 关键字。
//await 关键字的用法
//必须书写在一个有 async 关键字的函数内;
//await 后面等待的内容必须是一个 promise 对象;
//本该使用then接收的结果,可以直接定义变量接收。
//缺点
1. await 只能捕获到 promise 成功的状态;
2. 如果失败,会报错,终止程序继续执行。
//解决方案
//1. 使用 try catch 语法
//语法: try { 执行代码 } catch(err) { 执行代码 };
//首先执行 try 里面的代码, 如果不报错, catch 的代码不执行了;
//如果报错, 不会爆出错误, 不会终止程序执行, 而是执行 catch 的代码, 把错误信息给到 err 参数。
//2. 改变封装 Promise 的思路
//让当前的 Promise 对象百分百成功,让成功和失败都按照 resolve 的形式来执行,只不过传递出去的参数, 记录一个表示成功或者失败的信息。
//封装一个加载图片的函数
function loadImg(url){
//返回一个promise对象
return new Promise((resolve,reject) => {
//创建一个img对象
let img = new Image();
//设置src属性
img.src = url;
//注册成功的事件
img.onload = function(){
resolve(img);
}
//注册失败的事件
img.onerror = function(){
resolve(new Error('图片加载失败'));
}
})
}
//准备一个数组,存放图片
let arr_img = ['./img/1.webp','./img/2.webp','./img/3.webp'];
async function fn(){ //处理异步程序
//await : 将异步转为同步执行
let img = await loadImg(arr_img[10]); //异步程序,返回一个promise对象.
if(img instanceof Error){
console.log(img);
}else{
document.body.appendChild(img); //添加到页面中
}
}
fn();
面试版-ajax
<script>
//面试题 :使用promise封装ajax
let ajax = {
get(url){ //url fnWin fnFaild
//返回一个promise对象
return new Promise((resolve,reject) => {
//1. 创建xhr对象
let xhr = new XMLHttpRequest();
//2. 与服务器建立连接
xhr.open('get',url,true);
//3. 注册事件
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(/^(2|3)\d{2}$/.test(xhr.status)){
//调用resolve
resolve(xhr.responseText);
}else{
//调用reject
reject();
}
}
}
//4. 发送请求
xhr.send();
})
},
post(url,data){
return new Promise((resolve,reject) => {
//1. 创建xhr对象
let xhr = new XMLHttpRequest();
//2. 与服务器建立连接
xhr.open('post',url,true);
//3. 注册事件
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(/^(2|3)\d{2}$/.test(xhr.status)){
//调用resolve
resolve(xhr.responseText);
}else{
//调用reject
reject();
}
}
}
//4. 发送请求
xhr.setRequestHeader('Content-type','Application/x-www-form-urlencoded');
xhr.send(data);
})
}
}
</script>
<script>
ajax.get('http://localhost:8888/test/first')
.then((data) => {
console.log(data);
})
.catch(() => {
console.log('请求失败');
})
ajax.get('http://localhost:8888/test/second')
.then((data) => {
console.log(JSON.parse(data));
})
.catch(() => {
console.log('请求失败');
})
ajax.get('http://localhost:8888/test/third?name=张三&age=18')
.then((data) => {
console.log(JSON.parse(data));
})
.catch(() => {
console.log('请求失败');
})
ajax.post('http://localhost:8888/test/fourth','name=张三&age=18')
.then((data) => {
console.log(JSON.parse(data));
})
.catch(() => {
console.log('请求失败');
})
</script>