Promise
定义
- 是一个构造函数,用于创建Promise实例对象
- 是一个容器,里面保存着一个尚未完成且预计在未来完成的异步操作
- 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数
注意
- Promise对象的状态只能改变一次
- 一个Promise对象重点关注它的状态和结果
- Promise对象如果为失败状态,必须处理,否则报错
1、创建promise
let res = new Promise((resolve,reject) => {
//resolve('123')
//reject('456')
})
//默认状态为pending,结果为undefined
resolve:是一个函数,pending -> fulfilledreject:是一个函数,pending -> rejected
影响状态改变的因素
- 返回非Promise值时,为成功状态,结果为
return返回的值 - 返回Promise值时,状态和结果跟随返回的Promise对象
- 出现异常情况时,为失败状态,结果为报错信息/抛出的值(
throw)
2、then方法
- 用于指定Promise对象成功状态和失败状态的回调函数
- then方法可以传入两个实参(函数),第一个是成功的回调,第二个是失败的回调
- then方法执行后返回一个新的Promise对象
- 可以链式调用
终止链式调用
ele.then(//ele1
(res1) => {
console.log('fulfilled...')
}
(res2) => {
console.log('rejected...')
//原理:返回一个进行中的promise对象 不会执行下一步
return new Promise(()=>{})
}
)//ele2
.then(
(res1) => {
console.log('fulfilled...')
}
(res2) => {
console.log('rejected...')
}
)
同步执行
//1.封装
function task(ele,time){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log(ele)
resolve('fulfilled...') //变为成功状态
},time)
})
}
-
then//2.then console.log('同步1') task(time1,1500) .then( (res) => { return task(time2,200) } ) .then( (res) => { return task(time3,800) } ) .catch((res) => { console.log('rejected...') }) console.log('同步2') -
异步函数:
async、awaitasync:异步函数await:等待后面Promsie对象成功状态的结果
//2.await (async function(){ console.log('同步1') await task('time1',1200) await task('time1',500) await task('time1',800) console.log('同步2') })()
自定义Promise
// 自执行函数 作用域
(function(){
function Promise(excutor){
this.status = 'pending'
this.result = undefined
this.callback = []
let _this = this //缓存this
/**
*状态只能改变一次
*可能性1:先改变状态,再执行
*可能性2:先执行,再改变状态 -> 定时器 -> 保存回调函数等待调用
*reject:失败 错误(console.lag) 抛出(throw)
*/
function resolve(resolveValue){
if(_this.status !== 'pending') return //锁定状态
_this.status = 'fulfilled'
_this.result = resolveValue
//遍历callback
if(_this.callback.length > 0){
_this.callback.foreach(item=>{
item.resloveCB(resolveValue)
})
}
}
function reject(rejectValue){
if(_this.status !== 'pending') return
_this.status = 'rejected'
_this.result = rejectValue
if(_this.callback.length > 0){
_this.callback.foreach(item=>{
item.rejectCB(rejectValue)
})
}
}
// 捕获错误
try{
excutor(resolve,reject)//执行器函数自执行
}catch(err){
reject(err)
}
}
Promise.prototype.then = function(){
/**
*then 同步执行 回调函数异步执行
*链式调用 -> 返回new promise
*跟随上一次的状态和结果
*返回值:
*promise对象 -> 判断状态
*非promose对象
*报错
*/
let _this = this
return new Promise = function(reslove,reject){
//设置回调函数默认返回值 传参
resloveCB=typeof resloveCB === 'function'?resloveCB:function(res){return res}
rejectCB=typeof rejectCB === 'function'?rejectCB:function(res){throw res}
//封装trycatch
function trycatch(callback){
//保存上一个的返回值
let result = callback(_this.result)
try{
if(result instanceof Promise){
//跟随上一个的状态和结果 -> then判断状态并执行
result.then(reslove,reject)
/*result.then(
(res)=>{reslove(res)},
(res)=>{reject(res)}
)*/
}
else{
//非promise对象
reslove(result)
}
}catch(err){
reject(err) //报错
}
}
if(_this.status === 'fulfilled'){
//异步执行
setTimeout(()=>{
trycatch(resloveCB)
})
}
else if(_this.status === 'rejected'){
setTimeout(()=>{
trycatch(rejectCB)
})
}
else if(_this.status === 'pending'){
/**
*先调用再改变状态
*多个then调用 多个回调函数 -> 数组对象
*保存回调函数等待调用
*/
_this.callback.push({
'resloveCB':function(){
trycatch(resloveCB)
}
'rejectCB':function(){
trycatch(resloveCB)
}
})
}
}
}
/**
*then 没有失败的回调函数
*catch 需要设置成功的回调函数默认值
*catch 返回promise对象
*/
Promise.prototype.catch = function(catchCB){
//成功的回调为null
return this.then(null,catchCB)
}
//静态方法
/**
*resolve 返回promise对象
*非promise对象 返回resolve
*promise对象 由对象的状态和结果决定
*/
Promise.resolve = function(value){
return new Promise((reslove,reject)=>{
if(value instanceof Promise){
value.then(reslove,reject)
}else{
reslove(value)
}
})
}
/**
*all 数组内所有成功返回reslove,则返回promise对象
*失败则返回第一个失败值
*传值与返值顺序一致 -> index
*/
Promise.all =function(arr){
return new Promise(reslove,reject)=>{
let results = [] //成功的数组
let count = 0 //成功的个数
arr.foreach((item,index)=>{
//Promise.reslove包装成promise对象
Promise.reslove(item).then(
(res)=>{
count++
results[index] = res
if(arr.length === count) reslove(results)
},
(res)=>{reject(res)}
)
}
}
}
//对外暴露
window.Promise = Promise
})()
用promise写一个路由
const routes = {
'/':home,
'/a":'a',
'/b':'b'
}
function router(path){
return new Promise((resolve,reject)=>{
if(routes[path]){
resolve(routes[path])
}
else{
reject('不存在')
}
})
}
router('/')
.then(res=>console.log(res))
.catch(err=>console.log(err))
promise封装ajax
function ajax(method,url,data){
return new Promise((resolve,reject)=>{
let xhr = new XMLHttpRquest()
xhr.open(method,url)
if(method === 'post'){
xhr.setRequestHeader('content-type','application/json;charset=utf-8')
}
xhr.onload = function(){
if(xhr.status>=200&&xhr.status<300){
resolve(xhr.response)
}
els{
reject({
status:this.status,
statusText:xhr.statusText
})
}
}
xhr.onerror = function(){
reject({
status:this.status,
statusText:xhr.statusText
})
}
})
if(method === 'post'){
xhr.send(JSON.stringify(data))
}
els if(method === 'get'){
xhr.send(data)
}
}