promises
- 首先,promise拥有三种状态,pending,fulfilled,rejected。
- 分别为过渡态到成功态,过渡态到拒绝态,且不可逆。
- promise拥有一个值保存数据,拥有一个状态决定功能,会有一个执行器函数。因此构造函数中拥有此三种变量或方法。
- 执行器函数拥有两个函数分别为resolve,reject,分别保存成功的值和状态与失败的值和状态。
- 此时我们需要解决的bug
- resolve和reject只能调一次(加一个状态判断,捕获调用好多次的异常
- then函数。then函数为resolve/reject执行之后的函数,因此需要添加一个状态。
- 此时then需要捕获异常。
- 此时我们需要解决的bug
- promise异步执行,then会提前。(在构造函数中放一个数组,专门存放将要执行的函数,将值循环遍历出去
- 捕获异常
- 此时的promise执行顺序不对,原生promise中,当promise中的函数异步的时候,会先执行普通代码,异步代码放在下一步执行。(定时器异步操作
- then的链式调用(返回一个promise
- 此时then存在的问题
- then的穿透,上方的判断如果函数为空,那么把空对象赋值给函数,此时把空对象改为静态数据
- 返回值分为两类,一类是普通字符串,一类为promise对象,因此需要做一个判断
- promise不可以在其中return自己(获取到promise自己,然后将自己与返回的数据做判断
- promise的静态方法(promise对象可直接调用resolve/reject进行返回
- promise的成员对象
- promise.all(),将获取到的值放在数组中与promise的数量做一个判断
- promise.race(),谁快用谁
用类的方法来写promise
声明HD.js
class HD{
//三种状态,pending->fulfilled,pending->rejected
//过度->成功,过渡->失败
static PENDING='pending'
static FULFILLED='fulfilled'
static REJECTED='rejected'
//构造函数,状态和传的值,以及改变状态的执行器
constructor(executor){
this.status=HD.PENDING
this.value=null
// 此bind()是在调用的时候改变this的指向到类,不然执行上下文调用的是window对象
executor(this.resolve.bind(this),this.reject.bind(this))
}
// 修改成功时候的值和状态
resolve(value){
// console.log(this);
this.status=HD.FULFILLED
this.value=value
}
// 修改失败时候的值和状态
reject(reason){
// console.log(this);
this.status=HD.REJECTED
this.value=reason
}
}
调用1.html
let p=new HD((resolve,reject)=>{
// 如果在这里修改value的值与状态是不符合规范的,因为promise是不可逆的
// resolve('解决')
reject('拒绝')
})
console.log(p);
单向以及异常
使resolve与reject调用之后不可更改HD.js
resolve(value){
// 只有在为pending的状态下才可以调用
// 意思为只能调用一次
if(this.status===HD.PENDING){
this.status=HD.FULFILLED
this.value=value
}
}
reject(reason){
// console.log(this);
if(this.status===HD.PENDING){
this.status=HD.REJECTED
this.value=reason
}
}
捕获异常HD.js
try {
executor(this.resolve.bind(this),this.reject.bind(this))
} catch (error) {
this.reject(error)
}
then
HD.js
then(onFulfilled,onRejected){
// 获取reject状态改变之后的值
// 成功才调
if(this.status===HD.FULFILLED){
onFulfilled(this.value)
}
if(this.status===HD.REJECTED){
onRejected(this.value)
}
}
拒绝的时候成功调用也不会报错
// 如果成功不为一个函数,那么定义成一个函数
if(typeof onFulfilled!=='function'){
onFulfilled=()=>{}
}
// 如果失败不为一个函数,那么定义成一个函数
if(typeof onRejected!=='function'){
onRejected=()=>{}
}
then捕获异常
if(this.status===HD.FULFILLED){
try {
// console.log('成功');
onFulfilled(this.value)
} catch (error) {
// console.log('出错');
onRejected(error)
}
}
if(this.status===HD.REJECTED){
try {
// console.log('成功出错');
onRejected(this.value)
} catch (error) {
// console.log('出错');
onRejected(error)
}
}
promise异步那么.then就会提前执行
此时如果是promise异步,那么.then就会直接执行,.then中的内容就会获取不到异步中的状态
// 构造函数中定义一个数组,放将要执行的函数
this.callbacks=[];
// .then中,如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
if(this.status===HD.PENDING){
this.callbacks.push({
onFulfilled,
onRejected
})
}
// resolve()
// 如果执行过resolve,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onFulfilled(value)
})
// ------------------------------------------------------------
// reject()
// 如果执行过reject,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onRejected(reason)
})
准备状态异常错误捕获
// 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
if(this.status===HD.PENDING){
this.callbacks.push({
// 对象属性
onFulfilled:value=>{
// 执行的函数
try {
onFulfilled(value);
} catch (error) {
onRejected(error)
}
},
onRejected:value=>{
// 执行的函数
try {
onRejected(value);
} catch (error) {
onRejected(error)
}
},
})
}
更改调用promise执行逻辑顺序
当resolve中的函数异步的时候,调用方式是函数外部,异步中的函数,异步结果放在下一次的then中执行(先执行异步中的非resolve和reject),因此我们需要在调用resolve/reject的时候使用异步。
resolve(value){
// console.log(this);
if(this.status===HD.PENDING){
this.status=HD.FULFILLED
this.value=value
// 使用异步来改变逻辑顺序
setTimeout(() => {
// 如果执行过resolve,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onFulfilled(value)
})
});
}
}
reject(reason){
// console.log(this);
if(this.status===HD.PENDING){
this.status=HD.REJECTED
this.value=reason
setTimeout(() => {
// 如果执行过reject,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onRejected(reason)
})
});
}
}
then链式调用接受前者参数
return promise
当前无法调用多次then,以及then的返回值
// then的最后
return new HD((resolve,reject)=>{
// 其中包括then的所有操作
})
then(onFulfilled,onRejected){
// 如果成功不为一个函数,那么定义成一个函数
// if(typeof onFulfilled!=='funciton'){
// onFulfilled=()=>{}
// }
// // 如果失败不为一个函数,那么定义成一个函数
// if(typeof onRejected!=='funciton'){
// onRejected=()=>{}
// }
return new HD((resolve,reject)=>{
// 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
if(this.status===HD.PENDING){
this.callbacks.push({
// 对象属性
onFulfilled:value=>{
// 执行的函数
try {
let result=onFulfilled(value)
// 改变状态
resolve(result)
// onFulfilled(value);
} catch (error) {
onRejected(error)
}
},
onRejected:value=>{
// 执行的函数
try {
// onRejected(value);
let result=onRejected(value)
reject(result)
} catch (error) {
onRejected(error)
}
},
})
}
// 获取reject状态改变之后的值
// 成功才调
if(this.status===HD.FULFILLED){
setTimeout(() => {
try {
// console.log('成功');
// 获取成功之后的返回值
let result=onFulfilled(this.value)
// 改变状态
resolve(result)
} catch (error) {
// console.log('出错');
onRejected('出错咯'+error)
}
});
}
if(this.status===HD.REJECTED){
setTimeout(() => {
try {
// console.log('成功出错');
let result=onRejected(this.value)
reject(result)
} catch (error) {
// console.log('出错');
onRejected(error)
}
});
}
})
}
新增链式promise异常处理
在上边的基础上直接调用reject而不是onRejected(error)
reject(error)
then的穿透
此时中间调用空的.then()就不会把值传递到下边的then
// 如果成功不为一个函数,那么定义成一个函数
if(typeof onFulfilled!=='function'){
onFulfilled=()=>this.value
}
// 如果失败不为一个函数,那么定义成一个函数
if(typeof onRejected!=='function'){
onRejected=()=>this.value
}
then return promise处理
当返回的值为promise对象时,进行判断
if(this.status===HD.FULFILLED){
setTimeout(() => {
try {
// console.log('成功');
// 获取成功之后的返回值
let result=onFulfilled(this.value)
// 改变状态
// resolve(result)
// 判断接受的是对象还是普通的字符串
if(result instanceof HD){
//如果是promise对象,那么再次调用then来返回得到的resolve的value
result.then(resolve,reject)
// 上述一行抵下面的所有
// result.then(
// value=>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// })
}else{
resolve(result)
}
} catch (error) {
// console.log('出错');
// onRejected('出错咯'+error)
// 当发生异常时调用reject
reject(error)
}
});
}
代码冗余优化
优化前
class HD{
static PENDING='pending'
static FULFILLED='fulfilled'
static REJECTED='rejected'
constructor(executor){
this.status=HD.PENDING
this.value=null
// 定义一个数组,放将要执行的函数
this.callbacks=[];
try {
executor(this.resolve.bind(this),this.reject.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve(value){
// console.log(this);
if(this.status===HD.PENDING){
this.status=HD.FULFILLED
this.value=value
// 使用异步来改变逻辑顺序
setTimeout(() => {
// 如果执行过resolve,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onFulfilled(value)
})
});
}
}
reject(reason){
// console.log(this);
if(this.status===HD.PENDING){
this.status=HD.REJECTED
this.value=reason
setTimeout(() => {
// 如果执行过reject,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onRejected(reason)
})
});
}
}
then(onFulfilled,onRejected){
// 如果成功不为一个函数,那么定义成一个函数
if(typeof onFulfilled!=='function'){
onFulfilled=()=>this.value
}
// 如果失败不为一个函数,那么定义成一个函数
if(typeof onRejected!=='function'){
onRejected=()=>this.value
}
return new HD((resolve,reject)=>{
// 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
if(this.status===HD.PENDING){
this.callbacks.push({
// 对象属性
onFulfilled:value=>{
// 执行的函数
try {
let result=onFulfilled(value)
// 改变状态
// resolve(result)
if(result instanceof HD){
result.then(resolve,reject)
}else{
resolve(result)
}
// onFulfilled(value);
} catch (error) {
// onRejected(error)
reject(error)
}
},
onRejected:value=>{
// 执行的函数
try {
// onRejected(value);
let result=onRejected(value)
// reject(result)
if(result instanceof HD){
result.then(resolve,reject)
}else{
resolve(result)
}
} catch (error) {
// onRejected(error)
reject(error)
}
},
})
}
// 获取reject状态改变之后的值
// 成功才调
if(this.status===HD.FULFILLED){
setTimeout(() => {
try {
// console.log('成功');
// 获取成功之后的返回值
let result=onFulfilled(this.value)
// 改变状态
// resolve(result)
// 判断接受的是对象还是普通的字符串
if(result instanceof HD){
//如果是promise对象,那么再次调用then来返回得到的resolve的value
result.then(resolve,reject)
// 上述一行抵下面的所有
// result.then(
// value=>{
// resolve(value)
// },
// reason=>{
// reject(reason)
// })
}else{
resolve(result)
}
} catch (error) {
// console.log('出错');
// onRejected('出错咯'+error)
// 当发生异常时调用reject
reject(error)
}
});
}
if(this.status===HD.REJECTED){
setTimeout(() => {
try {
// console.log('成功出错');
let result=onRejected(this.value)
// reject(result)
if(result instanceof HD){
result.then(resolve,reject)
}else{
resolve(result)
}
} catch (error) {
// console.log('出错');
// onRejected(error)
reject(error)
}
});
}
})
}
}
优化后
// 优化代码
parse(result,resolve,reject){
try {
if(result instanceof HD){
result.then(resolve,reject)
}else{
resolve(result)
}
} catch (error) {
reject(error)
}
}
// 调用函数举例
if(this.status===HD.FULFILLED){
setTimeout(() => {
this.parse(onFulfilled(this.value),resolve,reject)
});
}
if(this.status===HD.REJECTED){
setTimeout(() => {
this.parse(onRejected(this.value),resolve,reject)
});
}
promise不允许return自己
虽然是异步,但是不允许返回自己
//加上promise来与result做一次比较
parse(promise,result,resolve,reject){
if(promise===result){
throw new TypeError('Chaining cycle detected')
}
try {
if(result instanceof HD){
result.then(resolve,reject)
}else{
resolve(result)
}
} catch (error) {
reject(error)
}
}
// 得到promise
let promise= new HD((resolve,reject)=>{}
return promise;
reject与resolve的静态方法
直接调用
// 测试
let promise=new HD((resolve,reject)=>{
resolve('解决')
})
HD.resolve(promise).then(value=>{
console.log(value);
})
static resolve(value){
return new HD((resolve,reject)=>{
if(value instanceof HD){
value.then(resolve,reject)
}else{
resolve(value)
}
})
}
static reject(value){
return new HD((resolve,reject)=>{
reject(value)
})
}
promise.all()
获取全部的promise,而且全部判断是否成功
static all(promises){
const values=[]
return new HD((resolve,reject)=>{
promises.forEach((promise=>{
promise.then(
value=>{
values.push(value)
if(values.length==promises.length){
resolve(values)
}
},reason=>{
reject(reason)
})
}))
})
}
promise.race()
谁快用谁
static race(promises){
return new HD((resolve,reject)=>{
promises.map(promise=>{
promise.then(value=>{
resolve(value)
},reason=>{
reject(reason)
})
})
})
}
完整代码
class HD{
static PENDING='pending'
static FULFILLED='fulfilled'
static REJECTED='rejected'
constructor(executor){
this.status=HD.PENDING
this.value=null
// 定义一个数组,放将要执行的函数
this.callbacks=[];
try {
executor(this.resolve.bind(this),this.reject.bind(this))
} catch (error) {
this.reject(error)
}
}
resolve(value){
// console.log(this);
if(this.status===HD.PENDING){
this.status=HD.FULFILLED
this.value=value
// 使用异步来改变逻辑顺序
setTimeout(() => {
// 如果执行过resolve,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onFulfilled(value)
})
});
}
}
reject(reason){
// console.log(this);
if(this.status===HD.PENDING){
this.status=HD.REJECTED
this.value=reason
setTimeout(() => {
// 如果执行过reject,那么调用.then成功函数,把值传过去
this.callbacks.map(callback=>{
callback.onRejected(reason)
})
});
}
}
then(onFulfilled,onRejected){
// 如果成功不为一个函数,那么定义成一个函数
if(typeof onFulfilled!=='function'){
onFulfilled=()=>this.value
}
// 如果失败不为一个函数,那么定义成一个函数
if(typeof onRejected!=='function'){
onRejected=()=>this.value
}
let promise= new HD((resolve,reject)=>{
// 如果处于pending状态,那么不执行.then里边的函数,把函数压入callback数组中
if(this.status===HD.PENDING){
this.callbacks.push({
// 对象属性
onFulfilled:value=>{
this.parse(promise,onFulfilled(value),resolve,reject)
},
onRejected:value=>{
this.parse(promise,onRejected(value),resolve,reject)
},
})
}
// 获取reject状态改变之后的值
// 成功才调
if(this.status===HD.FULFILLED){
setTimeout(() => {
this.parse(promise,onFulfilled(this.value),resolve,reject)
});
}
if(this.status===HD.REJECTED){
setTimeout(() => {
this.parse(promise,onRejected(this.value),resolve,reject)
});
}
})
return promise;
}
// 优化代码
parse(promise,result,resolve,reject){
if(promise===result){
throw new TypeError('Chaining cycle detected')
}
try {
if(result instanceof HD){
result.then(resolve,reject)
}else{
resolve(result)
}
} catch (error) {
reject(error)
}
}
static resolve(value){
return new HD((resolve,reject)=>{
if(value instanceof HD){
value.then(resolve,reject)
}else{
resolve(value)
}
})
}
static reject(value){
return new HD((resolve,reject)=>{
reject(value)
})
}
static all(promises){
const values=[]
return new HD((resolve,reject)=>{
promises.forEach((promise=>{
promise.then(
value=>{
values.push(value)
if(values.length==promises.length){
resolve(values)
}
},reason=>{
reject(reason)
})
}))
})
}
static race(promises){
return new HD((resolve,reject)=>{
promises.map(promise=>{
promise.then(value=>{
resolve(value)
},reason=>{
reject(reason)
})
})
})
}
}