1.promise是什么?
promise是异步编程的一种解决方案,解决多个异步方法串行的问题,比如回调地狱等.所谓的promise,简单地说就是一个容器,里面保存着某个未来才会结束的事件,从语法说promise是一个对象,从他可以获取异步操作的消息。promise提供统一的api,各种操作都可以用相同的方法进行处理.
2.promise的特点
1.对象的状态不收外界影响,promise对象代表一个异步操作,有三种状态pending(进行中),fulfilled(已成功)和rejected(已失败)。只有一步的操作结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2.一旦状态改变,就不会在编,任何时候都可以得到这个结果。promise对象的状态改变只有两种可能:从pending变为fulfilled或从pending变为rehected.
2.基本用法
ES6规定,promise对象是一个构造函数,用来生成Promise实例。
promise默认传入exectutor执行器 立即执行。
promise提供两个方法reslove和reject.
promise实例生成后,可以用then方法分别指定resloved状态和rejected状态的回调函数.
let p1=new Promise((reslove,reject)=>{
if(true){
reslove('成功')
}else{
reject('失败')
}
})
p1.then((data)=>{
//成功的回调
console.log(data)
},(err)=>{
//失败的回调
console.log(err)
})
基本用法的简单实现
//1.exectutor执行器 立即执行
//三种状态默认是等待态 resolve成功态 reject失败态
const PENDING='PENDING'
const RESOLVE='RESOLVE'
const REJECT='REJECT'
class Promise{
constructor(exectutor){
//成功状态的取值
this.success_val=undefined;
//失败状态的取值
this.error_val=undefined;
//状态
this.status=PENDING;
//成功回调
let resolve=(val)=>{
//判断如果是等待态 将状态赋值 不能再修改状态
if(this.status===PENDING){
this.success_val=val;
this.status=RESOLVE;
}
}
//失败回调
let reject=(err)=>{
//同上
if(this.status===PENDING){
this.error_val=err;
this.status=REJECT
}
}
try{
exectutor(resolve,reject)
}catch(err){
//如果是 throw err直接手动调用reject
reject(err)
}
}
then(successFn,errFn){
//then会传入两个回调函数 一个成功一个失败
//如果状态是成功态 successFn执行
if(this.status===RESOLVE){
successFn(this.success_val)
}
//反之
if(this.status===REJECT){
errFn(this.error_val)
}
}
}
promise里面setTimeout几秒后resolve或者reject结果,异步操作,这时候需要用到发布订阅模式.
const Promise=require('./promise.js')
let p1=new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('成功')
},3000)
})
p1.then((data)=>{
console.log(data)
},(err)=>{
console.log(err)
})
//此时promise应该是等待态
const PENDING='PENDING'
const RESOLVE='RESOLVE'
const REJECT='REJECT'
class Promise{
constructor(exectutor){
//成功状态的取值
this.success_val=undefined;
//失败状态的取值
this.error_val=undefined;
//状态
this.status=PENDING;
//成功数组里存放执行器
this.success_arr=[];
//失败数组里存放执行器
this.err_arr=[];
//成功回调
let resolve=(val)=>{
//判断如果是等待态 将状态赋值 不能再修改状态
if(this.status===PENDING){
this.success_val=val;
this.status=RESOLVE;
//promise 成功态后只需依次执行this.success里的函数即可
this.success_arr.forEach(fn=>{
fn()
})
}
}
//失败回调
let reject=(err)=>{
//同上
if(this.status===PENDING){
this.error_val=err;
this.status=REJECT
this.err_arr.forEach(fn=>{
fn()
})
}
}
try{
exectutor(resolve,reject)
}catch(err){
//如果是 throw err直接手动调用reject
reject(err)
}
}
then(successFn,errFn){
//then会传入两个回调函数 一个成功一个失败
//如果状态是成功态 successFn执行
if(this.status===RESOLVE){
successFn(this.success_val)
}
//反之
if(this.status===REJECT){
errFn(this.error_val)
}
//有异步操作这时promise的状态为pedding
if(this.status===PENDING){
this.success_arr.push(()=>{
//添加一个函数代码可拓展 增加别的逻辑 successFn执行的时候 当前状态已改为成功态 this.success的值已经改变
successFn(this.success_val)
})
this.err_arr.push(()=>{
errFn(this.error_val)
})
}
}
}
module.exports=Promise;
promise中的链式调用类似于jquery的链式调用,不同的是jquery返回的是this,promise返回的是一个新的promise。
-
then放方法中(成功或者失败)只要不是返回一个promise,都会将结果返回到下一个then中成功的回调函数.
let p1=new Promise((resolve,reject)=>{
resolve('成功')
})
p1.then((data)=>{
console.log(data) //成功
return 2
},(err)=>{
console.log(err)
}).then((data)=>{
console.log(data) //2
},(err)=>{
console.log(err)
})
let p1=new Promise((resolve,reject)=>{
reject('失败')
})
p1.then((data)=>{
return 2
},(err)=>{
return err
}).then((data)=>{
console.log('success',data) //success 失败
},(err)=>{
console.log('err',err)
})
-
如果then方法中抛出异常(throw new Error),会将结果返回到下一个then的失败的回调函数.
let p1=new Promise((resolve,reject)=>{
resolve('成功')
})
p1.then((data)=>{
throw new Error('成功回调里 抛出异常')
},(err)=>{
return err
}).then((data)=>{
console.log('success',data)
},(err)=>{
console.log('err',err) //err Error: 成功回调里 抛出异常
})
-
如果返回一个promise,会将这个promise的返回结果,作为下一次then里成功或者失败.
//新promise成功返回
let p1=new Promise((resolve,reject)=>{
resolve('成功')
})
p1.then((data)=>{
return new Promise((resolve,reject)=>{
resolve('新promise成功')
})
},(err)=>{
return err
}).then((data)=>{
console.log('success',data) //success 新promise成功
},(err)=>{
console.log('err',err)
})
//新promise失败返回
let p1=new Promise((resolve,reject)=>{
resolve('成功')
})
p1.then((data)=>{
return new Promise((resolve,reject)=>{
reject('新promise失败') //throw new Error('新promise失败') 同理
})
},(err)=>{
return err
}).then((data)=>{
console.log('success',data)
},(err)=>{
console.log('err',err) //err 新promise失败
})
-
catch错误捕获,先找距离自己近的如果没有错误捕获,会找到最终的catch方法.如果catch返回一个普通值,会将catch结果返回到下一次then的成功回调中。
let p1=new Promise((resolve,reject)=>{
resolve('成功')
})
p1.then((data)=>{
return new Promise((resolve,reject)=>{
reject('新promise失败')
})
},(err)=>{
return err
}).then((data)=>{
console.log('success',data)
},(err)=>{
console.log('err',err) //err 新promise失败
}).catch(err=>{
console.log('catch err',err) //会找最近的 err回调 如果前面定义了err回调 不会走catch错误被捕获
})
//前面没有错误捕获会走到catch方法
let p1=new Promise((resolve,reject)=>{
resolve('成功')
})
p1.then((data)=>{
return new Promise((resolve,reject)=>{
reject('新promise失败')
})
},(err)=>{
return err
}).then((data)=>{
console.log('success',data)
}).catch(err=>{
console.log('catch err',err) //catch err 新promise失败
})
//如果catch返回一个普通值,会将catch结果返回到下一次then的成功回调中
let p1=new Promise((resolve,reject)=>{
resolve('成功')
})
p1.then((data)=>{
return new Promise((resolve,reject)=>{
reject('新promise失败')
})
},(err)=>{
return err
}).then((data)=>{
console.log('success',data)
}).catch(err=>{
console.log('catch err',err)
return err
}).then(data=>{
console.log('catch success',data) //catch success 新promise失败
})
基于以上特点实现一个完整的promise
const PENDING='PENDING'
const RESOLVE='RESOLVE'
const REJECT='REJECT'
function resolvePromise(promise2,x,resolve,reject){
//循环引用报错 是同一个对象
if(promise2===x){
return reject(new TypeError('Chaining cycle detected for promise'));
}
//防止多次调用
let called;
//判读then的返回结果是普通值还是promise
if(typeof x!==null&&(typeof x==='function' || typeof x==='object')){
try{
let then=x.then;
//如果是promise
if(typeof then==='function'){
//成功的回调函数
then.call(x,data=>{
if(called) return;
called=true;
//如果返回的还是promise 继续解析,递归调用
resolvePromise(promise2,data,resolve,reject)
},err=>{
if(called) return;
called=true;
reject(err)
})
}else{
//如果是对象
resolve(x)
}
}catch(err){
//如果then抛出异常直接调用reject
if(called) return;
called=true;
reject(err)
}
}else{
//普通值直接返回x
resolve(x)
}
}
class Promise{
constructor(exectutor){
//成功状态的取值
this.success_val=undefined;
//失败状态的取值
this.error_val=undefined;
//状态
this.status=PENDING;
//成功数组里存放执行器
this.success_arr=[];
//失败数组里存放执行器
this.err_arr=[];
//成功回调
let resolve=(val)=>{
//判断如果是等待态 将状态赋值 不能再修改状态
if(this.status===PENDING){
this.success_val=val;
this.status=RESOLVE;
//promise 成功态后只需依次执行this.success里的函数即可
this.success_arr.forEach(fn=>{
fn()
})
}
}
//失败回调
let reject=(err)=>{
//同上
if(this.status===PENDING){
this.error_val=err;
this.status=REJECT
this.err_arr.forEach(fn=>{
fn()
})
}
}
try{
exectutor(resolve,reject)
}catch(err){
//如果是 throw err直接手动调用reject
reject(err)
}
}
then(successFn,errFn){
//判断 如果successFn不是一个函数 直接将结果返回 防止报错
successFn= typeof successFn==='function' ? successFn:v=>v
errFn=typeof errFn==='function' ? errFn:err=>{throw err}
//首先每次promise.then会返回一个新的promise
let promise2=new Promise((resolve,reject)=>{
if(this.status===RESOLVE){
//拿到promise成功回调执行后的结果 判断是否是promise还是普通值.此时promise2还没有生成 需要异步执行 setTimeout
setTimeout(()=>{
//如果抛出异常 直接就reject返回错误结果
try{
let x=successFn(this.success_val)
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
},0) //默认最少0.4毫秒执行
}
//反之
if(this.status===REJECT){
setTimeout(()=>{
//如果抛出异常 直接就reject返回错误结果
try{
let x=errFn(this.error_val)
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
},0) //默认最少0.4毫秒执行
}
//有异步操作这时promise的状态为pedding
if(this.status===PENDING){
this.success_arr.push(()=>{
//添加一个函数代码可拓展 增加别的逻辑 successFn执行的时候 当前状态已改为成功态 this.success的值已经改变
try{
let x=successFn(this.success_val)
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
})
this.err_arr.push(()=>{
try{
let x=errFn(this.error_val)
resolvePromise(promise2,x,resolve,reject)
}catch(err){
reject(err)
}
})
}
})
// 创建一个新的promise并返回
return promise2;
}
}
module.exports=Promise;
catch实现
catch(errFn){
return this.then(null,errFn)
}
finally的实现
//finally
finally(fn){
this.then(value=>{
fn()
return value
},err=>{
fn()
throw err
})
}
网友评论