一、同步和异步
1.1 吃外卖的文学-同步和异步
采用异步方式时, 在空闲期间我们可以做其他事情。
而同步时,我们在空闲期间只能等待, 什么事都不做
1.2 同步和异步的区别
在计算机领域,
同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到收到返回信息才继续执行下去;
异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率
1.3 js代码的执行顺序-同步和异步
js的执行顺序,先同步后异步
如上图:任务二属于异步代码(耗时操作)
异步任务:
- 定时器:setTimeout setInterval
- ajax的异步请求的xhr.onreadystate = function(){}
- es6的promise
console.log(1);
setTimeOut(function(){
console.log(2);
},0)
console.log(3);
-------------------------------
console.log(1);
var xhr = new XMLHttpRequest();
console.log(2);
xhr.open('get','checkUser.php?username='+this.value);
console.log(3);
xhr.send();
console.log(4);
xhr.onreadystatechange = function(){
if (xhr.readyState==4&&xhr.status==200) {
console.log(5);
}
}
console.log(6);
1.4、获取取异步函数返回值
function getNum(){
return 1;
}
function getNum(){
setTimeOut(function(){
return 1;
},1000);
}
------------------------------------
解决方案:回调函数来解决
function getNum(callback){
setTimeout(function(){
callback(1);
},500)
}
getNum(function(data){
console.log(data);
})
1.5 多个异步任务,顺序执行
1.5.1 回调函数嵌套
setTimeout(function () {
console.log(1);
setTimeout(function () {
console.log(2);
setTimeout(function () {
console.log(3);
setTimeout(function () {
console.log(4);
}, 2000)
}, 3000)
}, 5000)
}, 1000)
问题:
- 代码丑,冗杂,难维护
- 执行效率低
1.5.2 Promise解决(下面讲解)
问题:编写的难度比传统写法高,并且阅读代码也不是一眼能够看懂。
你只会看到一堆then,必须本身在then的回调函数里面理清逻辑。
三、Promise完美解决回调地狱
3.1 Promise对象
Promise(承诺),在程序中的意思就是承诺我过一段时间(通常是一个异步操作)后会给你一个结果,是异步编程的一种解决方案。
从语法上说,原生Promise 是一个对象,从它可以获取异步操作的消息
Promise 提供统一的 API,各种异步操作都可以用同步的写法进行处理。
3.2 Promise实现原理
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve 和 reject。
它们是两个函数,由 JavaScript 引擎提供,不用自己部署。
promise对象的方法:
- then()方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数
- 而 Promise的优势就在于这个链式调用。
- 我们可以在 then 方法中继续写 Promise 对象并返回,然后继续调用 then 来进行回调操作。
cpnst p = new Promise(
function (resolve, reject) {
// 一段耗时的异步操作
resolve('成功') // 获取成功的数据
// reject('失败') //获取失败的结果
}
).then(res=>{console.log(res)})
-----------------------------------------------
const p1 = new Promise(function(resolve,reject){
resolve(1)
})
const p2 = new Promise(function(resolve,reject){
resolve(2)
})
const p3 = new Promise(function(resolve,reject){
resolve(3)
})
const p4 = new Promise(function(resolve,reject){
resolve(4)
})
p1.then(data=>{console.log(data);return p2;})
.then(data=>{console.log(data);return p3;})
.then(data=>{console.log(data);})
3.3 Promise特点
- 对象的状态不受外界影响。
promise有三种状态 pending(进行中) fulfilled(已成功) rejected(已失败),只有异步操作的结果,才可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。一旦从等待状态变成为其他状态就永远不能更改状态了。
promise只有两种状态改变:
pending(进行中)–> fulfilled(已成功) ;
pending(进行中)–> rejected(已失败)。
当状态改变结束时称为resolve(已固·定),一旦状态变为 resolved 后,就不能再次改变为Fulfilled。
一旦新建Promise就会立即执行,无法中途取消
let p = new Promise((resolve, reject) => {
let n = Math.round(Math.random() * 10 + 10);//10-20
if (n <= 15) {
resolve(n)
} else {
reject(n);
}
})
console.log(p);//promise对象
p对象:.then()拿到处理成功的结果 .catch()拿处理失败的结果的
p.then(data=>{
console.log(data);
}).catch(data=>{
console.log(data);
})
三个状态:"pending", "fulfilled","rejected"
2个方法:.then() .catch()
3.4 使用Promise封装ajax
function $promise(options) {
return new Promise((resolve, reject) => {
// 1. 创建xhr对象 XMLHTTPRequset
let xhr = new XMLHttpRequest();
let params = formdata(options.data);
// 2. 设置请求参数(分get和post)
if (options.type == 'GET') {
xhr.open('get', options.url + '?' + options.data, true);
xhr.send();
}
if (options.type == 'POST') {
xhr.open('post', options.url);
xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
xhr.send( options.data);
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve(xhr.responseText)
} else {
reject('错误');
}
}
}
})
}
$promise({
type: "GET",
url: 'a.php',
asycn: true,
data: "username=zhangsan"
}).then(data => {
console.log(data);
})
四、async 和await(了解)
用async/ await来发送异步请求,从服务端获取数据,代码很简洁
async/await:基于prmoise,await修饰promise对象,async 修饰函数
function getNum1(){
return 1;
}
function getNum2(){
return 2;
}
async function fn(){
let res1 = await getNum1();
let res2 = await getNum2();
console.log(res1);
console.log(res2);
}
fn();