异步新增
Promise
Promise 有三个状态,pending挂起状态,fulfulled成功状态,rejected失败状态,这三种状态只能由挂起到成功或失败状态这两条途径,而且一旦成功或失败状态就不可更改,所以在new一个 promise 实例时只要执行了一个resolve或reject之后再执行的resolve和reject将毫无意义
构造方法
- 参数必须是一个函数,否则会报错,并且该函数会立即同步执行
- 该回调函数有两个参数
resolve和reject也是函数类型,这两个参数改变状态的代码由 js 引擎实现resolve:代表成功的回调函数,会将该 promise 状态转化为fulfulled成功状态value:该函数有一个参数用来保存成功的结果
reject:代表失败的回调函数,会将该 promise 状态转化为rejected失败状态,失败状态必须要处理,否则会有警告reason:该函数有一个参数用来保存失败的结果
- 抛出错误,相当于执行
reject (error)
静态方法
| 方法名 | 描述 |
|---|---|
Promise.Resolve (object) |
无参,则将返回一个空的且状态是成功的 promise 对象;参数若是普通值,则将该值放入一个状态为成功的 promise 对象中并返回;参数若是 promise 对象,则原封不动返回该对象;参数若是一个带有then ()方法的对象,会立即异步的执行这个then ()方法,该then ()方法中可以控制返回 promise 状态,也就是说该then ()方法也有两个函数类型参数,一个是resolve和reject |
Promise.Reject (reason) |
将reason放入一个状态为rejected的 promise 对象中并返回 |
Promise.All (pramises) |
接收一个集合,若数组元素不是 promise 对象会先调用Promise.Resolve ()方法包装成一个 promise 对象,返回一个 promise 对象,该对象的状态和值由 promises 集合中所有对象的执行结果决定,全部成功则返回的 promise 对象状态就是成功的,值就是以数组形式对应的执行结果的值,有一个失败则返回的 promise 对象状态就是失败的,值是第一个失败的结果 |
Promise.Race (pramises) |
接收一个集合,若数组元素不是 promise 对象会先调用Promise.Resolve ()方法包装成一个 promise 对象,返回一个 promise 对象,该对象的状态和值由 promises 数中所有对象的执行结果决定,总是返回第一个完成的 promise 对象,无论是成功还是失败 |
Promise.AllSettled (pramises) |
接收一个集合,若数组元素不是 promise 对象会先调用Promise.Resolve ()方法包装成一个 promise 对象,返回一个 promise 对象,该对象的状态为成功的 promise 对象,只不过该对象的值是将 promises 集合中每个 promise 对象的返回值都封装成了 promise 对象,这些 promise 对象的状态由上一次的执行结果决定 |
实例方法
| 方法名 | 描述 |
|---|---|
Promise.Prototype.Then (resolve[, reject]) |
resolve是成功状态的回调函数,reject是失败状态的回调函数且可省略,并且这些回调是异步执行的;返回一个新的 promise 对象,由执行这两个回调函数的返回值决定;返回一个普通值=成功的包装该值的 promise 对象,返回一个 promise 对象=该 promise 对象,抛出错误=返回一个包装该错误的 promise 对象 |
Promise.Prototype.Catch (reject) |
reject是失败的回调函数,相当于调用then (undefuned, reject)方法所以,返回的 promise 对象与then ()方法一致 |
Promise.Prototype.Finally (close) |
close是无论当前 promise 是什么状态都会执行的的回调函数,无论该回调中是有retuen语句,总是返回一个值为undefined状态为成功的 promise 对象 |
Promise 应用
可以达到串行执行异步任务的效果
New Promise ((resolve, reject)=>{
SetTimeout (()=>{
Resolve (1);
}, 1000);
}). Then ((value)=>{
Return new Promise ((resolve, reject)=>{
SetTimeout (()=>{
Resolve (value+"处理 value 后");
}, 500)
})
}). Then ((value)=>{
Console.Log (value);
}). Catch ((error)=>{
Console.Log (error);
})
Promise 原理
Const PENDING = Symbol ("pending"); //挂起状态
Const REJECTED = Symbol ("rejected"); //失败状态
Const FULFULLED = Symbol ("fulfilled"); //成功状态
/*
Promise: 构造函数,创建 promise 实例
Excutor: 执行器函数,同步立即执行
*/
Function Promise (excutor) {
Const self = this; //保存当前函数 this 方便在内部函数使用
This. Status = PENDING; //当前 promise 对象的状态,初始是 pending
This. Data = undefined; //存储结果数据
This. Callbacks = []; //回调函数队列,元素以{ onResolved (){}, onRejected (){} }形式保存
Try { //若执行器执行抛出异常则说明该 promise 是失败的
Excutor (resolve, reject); //立即执行执行器函数
} catch (error) { //将抛出的错误信息当作失败回调函数的 reason
Reject (error)
}
/*
Resolve: 将当前 promise 对象状态转为 fulfilled,保存 value 到当前 promise 对象的 data 中,异步执行函数队列中成功的回调函数
Value: 成功的结果
*/
Function resolve (value) {
If (self. Status !== PENDING) return; //状态只能是从 pending 到其他状态,若已是成功或失败则不需要执行该函数
Self. Status = FULFULLED; //改变状态为成功 fulfilled
Self. Data = value; //保存 value 到 promise 的 data 中
SetTimeout (() => { //若在调用 resolve 之前为此 promise 对象绑定了回调函数,则依次异步执行这些回调函数
For (let i = 0; i < self. Callbacks. Length; i++) { //遍历函数执行队列并执行成功的回调
Self. Callbacks[i]. OnResolved ();
}
});
}
/*
Reject: 将当前 promise 对象状态转为 rejected,保存 reason 到当前 promise 对象的 data 中,异步执行函数队列中失败的回调函数
Reason: 失败的原因
*/
Function reject (reason) {
If (self. Status !== PENDING) return; //状态只能是从 pending 到其他状态,若已是成功或失败则不需要执行该函数
Self. Status = REJECTED; //改变状态为失败 rejected
Self. Data = reason; //保存 reason 到 promise 的 data 中
SetTimeout (() => { //若在调用 reject 之前为此 promise 对象绑定了回调函数,则依次异步执行这些回调函数
For (let i = 0; i < self. Callbacks. Length; i++) { //遍历函数执行队列并执行失败的回调
Self. Callbacks[i]. OnRejected ();
}
});
}
}
/*
Then: 为当前对象绑定回调函数,再根据回调返回值指返回一个新的 promise 对象
OnResolved: 成功的回调函数
OnRejected: 失败的回调函数
*/
Promise. Prototype. Then = function (onResolved, onRejected) {
Const self = this; //保存当前函数 this 方便在内部函数使用
OnResolved = typeof onResolved === "function" ? OnResolved : value => value; //传入参数是非函数,指定回调向下传递参数即可
OnRejected = typeof onRejected === "function" ? OnRejected : reason => { throw reason } //省略错误回调,向下传递抛出错误,在 handle 函数中会转化为失败的 promise 达到向下传递错误的目的
Return new Promise ((resolve, reject) => { //返回一个新的 promise 对象
/*
Handle: 统一处理 onResolved 或 onRejected 指定回调中抛出错误、promise 对象、普通值的情况,从而决定返回新的 promise 对象的状态
Callback: 同步的回调函数,主要使用该回调函数的返回值指定决定新的 promise 对象的状态
*/
Function handle (callback) {
Try { //若执行指定回调函数抛出错误则说明该 promise 是失败的
Const result = callback (self. Data); //取得回调函数的返回值
If (result instanceof Promise) { //若返回值是 promise 对象
Result.Then (resolve, reject); //则新的 promise 对象的状态由该返回的 promise 对象的状态决定
} else { //若返回值是普通值则
Resolve (result); //则新的 promise 对象的状态是成功的
}
} catch (error) { //将抛出的错误信息当作失败回调函数的 reason
Reject (error);
}
}
Switch (self. Status) {
Case PENDING: //若当前 promise 对象状态是挂起状态,也就是创建 promise 对象时,执行器中的异步操作才执行到 resolve 或 reject 回调,即先绑定后执行
Self.Callbacks.Push ({ //将绑定的回调函数添加到回调队列上,等 promise 对象异步操作时执行 resolve 或 reject 回调再由执行器执行
OnResolved () { handle (onResolved) }, //将处理成功的回调按照回调队列要求包装在 onResolved 中
OnRejected () { handle (onRejected) } //将处理失败的回调按照回调队列要求包装在 onRejectedd 中
})
Break;
Case FULFULLED: //若当前 promise 对象状态是成功状态,也就是创建 promise 对象时,执行器中的同步操作执行到 resolve(不严谨),即先执行后绑定
SetTimeout (() => { handle (onResolved) });
//先执行后绑定是不可能的,只是执行了改变状态的代码,由于执行器其实是由于回调队列中是空的,就直接跳过了执行回调队列的操作, 要在调用 then 方法绑定成功回调时时立刻异步执行
// handle (onResolved);
Break;
Case REJECTED: //同理,若当前 promise 对象的状态是失败状态,也就是创建 promise 对象时,执行器中的同步操作执行到 reject 回调(不严谨),即先执行后绑定
SetTimeout (() => { handle (onRejected) });
//同样的,先执行后绑定是不可能的,只是执行了改变状态的代码,由于执行器其实是由于回调队列中是空的,就直接跳过了执行回调队列的操作, 要在调用 then 方法绑定失败回调时时立刻异步执行
// handle (onRejected);
Break;
}
});
}
/*
Catch: 为当前对象只绑定失败的回调函数,返回一个新的成功 promise 对象,并且新的 promise 对象的 data 是 undefined
Onrejected: 失败的回调
*/
Promise. Prototype. Catch = function (onrejected) {
Return this.Then (undefined, onrejected); //直接调用该对象的 then 方法,将成功的回调设置成非函数值,在 then 方法中会转化成向下传递值的回调函数,就会返回一个新的且 data 值是 undefined 的 promise 对象
}
/*
Resolve: 返回一个状态是成功且指定 data 为 value 的 promise 对象
Value: 可以是一个 promise 对象,可以是一个普通值
*/
Promise. Resolve = function (value) {
If (value instanceof Promise) { //若是一个 promise 对象
Return value; //则直接返回该 promise 对象
} else { //若是普通值
Return new Promise ((resolve, reject) => { //将值包装成成功的 promise 对象并返回
Resolve (value);
})
}
}
/*
Reject: 返回一个状态为失败的 promise 对象
Reason: 失败原因
*/
Promise. Reject = function (reason) {
Return new Promise ((resolve, reject) => {
Reject (reason);
});
}
/*
All: 返回一个 promise,只有当所有 promise 对象成功时才成功,否则失败
*/
Promise. All = function (promises) {
Const values = new Array (promises. Length); //创建一个与 promises 对应的数组,用来存放每个 promise 对象的返回值
Let count = 0; //成功的 promise 计数器
Return new Promise ((resolve, reject) => {
For (let i = 0; i < promises. Length; i++) { //遍历 promises 数组
Promise.Resolve (promises[i]). Then ( //数组元素若是普通值使用 Promise. Resolve 进行包装为成功的 promise 对象
Value => {
Count++; //每成功一个该计数器加一
Values[i] = value; //将执行成功回调函数的 value 添加到 values 对应位置
If (count === promises. Length) {
Resolve (values); //当所有都成功时,则返回的就是失败的 promise 对象,并且 data 值是 values 数组
}
},
Reason => { //只要有一个执行了失败的回调,则返回的就是失败的 promise 对象
Reject (reason)
}
)
}
});
}
/*
Race: 返回一个 promise,第一个完成的 promise 是成功的该返回的就是成功的 promise,第一个完成的 promise 是失败的该返回的就是失败的 promise
*/
Promise. Race = function (promises) {
Return new Promise ((resolve, reject) => {
For (let i = 0; i < promises. Length; i++) { //遍历 promises 数组
Promise.Resolve (promises[i]). Then (resolve, reject); //数组元素若是普通值使用 Promise. Resolve 进行包装为成功的 promise 对象
}
})
}
Generator 函数与异步
生成器函数可以依靠 yield 表达式暂停函数执行,若在异步回调函数中调用生成器函数返回的迭代器的 next 方法,就可以保证这些异步操作串行执行
Function* async () {
Let t = yield setTimeout (() => {
Console.Log (1);
It.Next ("yield 表达式的返回值"); //异步回调中调用当前生成器函数返回的迭代器的 next 方法
//甚至还可以使用带参的 next 方法指定 yield 表达式的值,来影响下一个异步任务
}, 2000);
Yield setTimeout (() => { //等到上个异步任务执行时才会启动该当前异步任务
Console.Log (t); //输出上一个异步任务指定的 yield 的表达式的值
}, 1000);
}
Let it = async (); //获取迭代器,该迭代器会在这个生成器函数中使用到
It.Next (); //开始执行生成器函数
若所有异步任务都使用 promise 对象进行封装,使用迭代器的 next 方法获取的对象其中 value 值就是指定的 promise 对象,promise 对象可以绑定多个成功或失败的回调,再为这些 promise 对象绑定一个调用该迭代器 next 的回调,就可以保证多个异步任务串行执行
Function autoRun (gen) {
Const g = gen (); //获取迭代器
Function next (data) {
const result = g.next (data); //向下执行生成器函数,并替换 yield 表达式的值,从而影响下一个异步任务
If (result. Done === false) { //若迭代器未结束
Promise.Resolve (result. Value) //若 yield 后不是 promise 对象则将他转化为成功的 promise 对象
.then (value => next (value)) //则为当前 promise 对象绑定执行迭代器 next 方法的函数
}
}
Next ();
}
AutoRun (function* () {
Let a = yield new Promise ((resolve, reject) => {
SetTimeout (() => {
Console.Log (1);
Resolve (2);
}, 1000)
});
A = yield new Promise ((resolve, reject) => {
SetTimeout (() => {
Console.Log (a);
Resolve (3);
}, 1000)
});
A = yield new Promise ((resolve, reject) => {
SetTimeout (() => {
Console.Log (a);
Resolve (1);
}, 1000)
});
});
Async 函数
声明
- 于普通的函数类似,只不过使用
async修饰的方法,但是不能作为构造函数那样使用 - 使用
return语句返回的必然是一个 promise 对象- 返回一个普通值=成功的包装该值的 promise 对象
- 返回一个 promise 对象=该 promise 对象
- 抛出错误=返回一个包装该错误的 promise 对象
Async function afun (){
// return 1; //Promise {<resolved>: 1}
// throw 1; //Promise {<rejected>: 1}
// return new Promise ((resolve, reject)=>{
// // resolve (1); //Promise {<resolved>: 1}
// // reject (1); //Promise {<rejected>: 1}
// //throw 1; //Promise {<rejected>: 1}
// })
}
Console.Log (afun ());
Await 表达式
- 只能在 async 函数中使用
- Await 后跟一个表达式
- 该表达式是一个 promise 对象,则该表达式的值是该 promise 对象成功的返回结果,如果该 promise 对象失败了就会抛出错误,需要用
try... Catch捕获错误才能得到该 promise 对象失败的返回结果 - 该表达式是一个普通表达式,则该表达式的值是这个普通表达式的值,即有没有 await 声明是一样的
- 该表达式是一个 promise 对象,则该表达式的值是该 promise 对象成功的返回结果,如果该 promise 对象失败了就会抛出错误,需要用
(async function () {
Const t = await Promise.Resolve (1);
Console.Log (t); //1
})();
//失败的 promise
(async function () {
Try {
Const t = await Promise.Reject (1);
Console.Log (t); //抛出错误,所以这里不会执行到
} catch (err) {
Console.Log (err); //1
}
})();
//普通表达式
(async function () {
Const t = await 1 + 1;
//等价于
// const t = 1 + 1;
Console.Log (t); //2
})();
Async 函数执行流程
- 调用该函数则该函数同步执行,只有遇到
await表达式并且右部是 promise 对象才会进入异步执行状态
Async function afun (){
Console.Log (1);
}
Afun ();
Console.Log (2);
// 1
// 2
Async function afun (){
Await Promise.Resolve ();
Console.Log (1);
}
Afun ();
Console.Log (2);
// 2
// 1
Async 实现原理
其实就是生成器函数自动串行执行的升级版,多绑定了一个失败的 promise 对象的回调函数
Function autoRun (gen) {
Return new Promise ((resolve, reject) => { //异步函数一定返回的是 promise 对象
Const g = gen (); //获取迭代器对象
Function next (data, status = 1) { //status 状态是 1 说明是成功的 promise,其他值则是失败的 promise
Let result; //保存迭代器结果对象
Try {
result = status === 1 ? g.next (data) : g.throw (data); //根据 status 决定将 yield 表达式替换为什么
//向下执行生成器函数,并替换 yield 表达式的值,从而影响下一个异步任务
} catch (e) { //若生成器函数中抛出错误
Reject (e); //则将错误捕获后,并将返回的 promise 对象变为失败的状态,reason 是捕获的错误信息
}
If (result. Done === false) { //若迭代器未结束
Promise.Resolve (result. Value) //若 yield 后不是 promise 对象则将他转化为成功的 promise 对象
.then (
(value) => next (value), //则为当前 promise 对象绑定成功的回调函数,其中中要执行迭代器 next 方法的函数
(error) => next (error, 0) //则为当前 promise 对象绑定失败的回调函数,其中中要执行迭代器 throw 方法的函数
);
} else { //若迭代器结束
Resolve (result. Value); //返回成功的 promise 对象,并且值是最后一个 return 语句后的值
}
}
Next ();
});
}

Comments NOTHING