异步处理与Promise
- 一、异步处理
- 1.两个阶段
- 2.事情三种状态
- 3.到达阶段后续处理
- 二、Promise
- 1.基本使用
- 2.注意点
- 3.事件和回调的优化
一、异步处理
ES官方参考了大量的异步场景,总结出了一套异步的通用模型,该模型可以覆盖几乎所有的异步场景,甚至是同步场景。
值得注意的是,为了兼容旧系统,ES6 并不打算抛弃掉过去的做法,只是基于该模型推出一个全新的 API,使用该API,会让异步处理更加的简洁优雅。
理解该 API,最重要的,是理解它的异步模型
1.两个阶段
ES6 将某一件可能发生异步操作的事情,分为两个阶段:unsettled 和 settled
unsettled: 未决阶段,表示事情还在进行前期的处理,并没有发生通向结果的那件事
settled:已决阶段,事情已经有了一个结果,不管这个结果是好是坏,整件事情无法逆转
事情总是从 未决阶段 逐步发展到 已决阶段的。并且,未决阶段拥有控制何时通向已决阶段的能力。
2.事情三种状态
ES6将事情划分为三种状态: pending、resolved、rejected
pending: 挂起,处于未决阶段,则表示这件事情还在挂起(最终的结果还没出来)
resolved:已处理,已决阶段的一种状态,表示整件事情已经出现结果,并是一个可以按照正常逻辑进行下去的结果
rejected:已拒绝,已决阶段的一种状态,表示整件事情已经出现结果,并是一个无法按照正常逻辑进行下去的结果,通常用于表示有一个错误
既然未决阶段有权力决定事情的走向,因此,未决阶段可以决定事情最终的状态!
我们将 把事情变为resolved状态的过程叫做:resolve,推向该状态时,可能会传递一些数据
我们将 把事情变为rejected状态的过程叫做:reject,推向该状态时,同样可能会传递一些数据,通常为错误信息
始终记住,无论是阶段,还是状态,是不可逆的!
3.到达阶段后续处理
当事情达到已决阶段后,通常需要进行后续处理,不同的已决状态,决定了不同的后续处理。
resolved状态:这是一个正常的已决状态,后续处理表示为 thenable
rejected状态:这是一个非正常的已决状态,后续处理表示为 catchable
后续处理可能有多个,因此会形成作业队列,这些后续处理会按照顺序,当状态到达后依次执行
整件事称之为Promise
二、Promise
1.基本使用
const pro = new Promise((resolve, reject)=>{
// 未决阶段的处理
// 通过调用resolve函数将Promise推向已决阶段的resolved状态
// 通过调用reject函数将Promise推向已决阶段的rejected状态
// resolve和reject均可以传递最多一个参数,表示推向状态的数据
});
pro.then(data=>{
//这是thenable函数,如果当前的Promise已经是resolved状态,该函数会立即执行
//如果当前是未决阶段,则会加入到作业队列,等待到达resolved状态后执行
//data为状态数据
}, err=>{
//这是catchable函数,如果当前的Promise已经是rejected状态,该函数会立即执行
//如果当前是未决阶段,则会加入到作业队列,等待到达rejected状态后执行
//err为状态数据
});
例:
const pro = new Promise((resolve,reject) =>{
console.log('未决阶段');
resolve(12345);//推向已决resolved状态
});
pro.then(data =>{
//处于已决resolved状态,后续的处理thenable
console.log(data);
});
const pro = new Promise((resolve,reject) =>{
console.log('未决阶段');
reject(12345);//推向已决rejected状态
});
pro.then(data =>{
console.log(data);
}, err =>{
//处于已决rejected状态,后续的处理catchable
console.log(err);
});
2.注意点
- 未决阶段的处理函数是同步的,会立即执行
const pro = new Promise((resolve, reject) => {
console.log("未决阶段");
console.log('推向resolved')
resolve(123);
console.log('马上结束')
});
pro.then(data => {
// pro的状态是resolved
console.log(data);
});
console.log('说完了');
- thenable和catchable函数是异步的,就算是立即执行,也会加入到事件队列中等待执行,并且,加入的队列是微队列
面试题重点
const pro = new Promise((resolve, reject) => {
console.log("未决阶段")
resolve(123);//微队列
setTimeout(() => {
console.log("来个定时器")
}, 0);//宏队列
console.log('马上说完');
});
pro.then(data => {
console.log(data);
});
pro.catch(err => {
console.log(err);
});
console.log("没话说了");
- pro.then可以只添加thenable函数,pro.catch可以单独添加catchable函数
const pro = new Promise((resolve, reject) => {
resolve(123);
})
pro.then(data => {
console.log(data);
});
pro.catch(err => {
console.log(err)
});
- 在未决阶段的处理函数中,如果发生未捕获的错误,会将状态推向rejected,并会被catchable捕获
const pro = new Promise((resolve, reject) => {
throw new Error("123"); // 推向pro: rejected
resolve(456);//不再执行
})
pro.then(data => {
console.log(data);
});
pro.catch(err => {
console.log(err)
});
- 一旦状态推向了已决阶段,无法再对状态做任何更改
const pro = new Promise((resolve, reject) => {
throw new Error("abc");
resolve(1); //无效
reject(2); //无效
resolve(3); //无效
reject(4); //无效
})
pro.then(data => {
console.log(data)
})
pro.catch(err => {
console.log(err)
})
const pro = new Promise((resolve, reject) => {
// throw new Error("abc");
resolve(1);
reject(2); //无效
resolve(3); //无效
reject(4); //无效
})
pro.then(data => {
console.log(data)
})
pro.catch(err => {
console.log(err)
})
- Promise并没有消除回调,只是让回调变得可控
3.事件和回调的优化
function biaobai(god) {
return new Promise(resolve => {
console.log(`我向${god}发出了表白短信`);
setTimeout(() => {
if (Math.random() < 0.1) {
//女神同意拉
resolve(true);
} else {
//无论是否同意,都是resolve,只有消息发不出去这种异常才是rejected
resolve(false);
}
}, 1000);
})
}
biaobai("女神1").then(result => {
console.log(`女神1${result}`);
});
biaobai("女神2").then(result => {
console.log(`女神2${result}`);
});
ajax({
url: "./data/students.json?name=李华",
...
}).then(resp => {
console.log(resp)
}, err => {
console.log(err)
});